Cru*_*ces 17 android unit-testing android-paging
我正在使用分页库从 api 检索数据并将它们显示在列表中
为此,我在我的存储库中创建了该方法:
fun getArticleList(query: String): Flow<PagingData<ArticleHeaderData>>
在我的视图模型中,我创建了如下所示的搜索方法:
override fun search(query: String) {
val lastResult = articleFlow
if (query == lastQuery && lastResult != null)
return
lastQuery = query
searchJob?.cancel()
searchJob = launch {
val newResult: Flow<PagingData<ArticleList>> = repo.getArticleList(query)
.map {
it.insertSeparators { //code to add separators }.cachedIn(this)
articleFlow = newResult
newResult.collectLatest {
articleList.postValue(it)
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了测试我的视图模型,我使用测试方法PagingData.from来创建一个从我的模拟存储库返回的流,如下所示:
whenever(repo.getArticleList(query)).thenReturn(flowOf(PagingData.from(articles)))
然后我从 articleList LiveData 中检索实际的分页数据,如下所示:
val data = vm.articleList.value!!
这将返回一个PagingData<ArticleList>对象,我想验证它是否包含来自服务的数据(即articles,何时返回)
我发现这样做的唯一方法是创建以下扩展函数:
private val dcb = object : DifferCallback {
override fun onChanged(position: Int, count: Int) {}
override fun onInserted(position: Int, count: Int) {}
override fun onRemoved(position: Int, count: Int) {}
}
suspend fun <T : Any> PagingData<T>.collectData(): List<T> {
val items = mutableListOf<T>()
val dif = object : PagingDataDiffer<T>(dcb, TestDispatchers.Immediate) {
override suspend fun presentNewList(previousList: NullPaddedList<T>, newList: NullPaddedList<T>, newCombinedLoadStates: CombinedLoadStates, lastAccessedIndex: Int): Int? {
for (idx in 0 until newList.size)
items.add(newList.getFromStorage(idx))
return null
}
}
dif.collectFrom(this)
return items
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但基于PagingDataDiffer标记为的类,@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)因此将来可能无法使用
有没有更好的方法可以flow从 PagingData (在库中标记为内部)或从中获取实际数据?
我在 Paging3 库上遇到了同样的问题,网上关于这个库的讨论还没有很多,但是当我翻阅一些文档时,我可能找到了一个解决方案。我面临的情况是试图确定数据列表中是否为空PagingData,然后我将以此为基础操作 UI。
下面是我在doc发现,有两种API中PagingDataAdapter已在版本增加了3.0.0-alpha04是peek(),和snapshot(),peek()为我们提供了基于索引的具体列表对象,而snapshot()让我们的整个列表。
所以这就是我所做的:
lifecycleScope.launch {
//Your PagingData flow submits the data to your RecyclerView adapter
viewModel.allConversations.collectLatest {
adapter.submitData(it)
}
}
lifecycleScope.launch {
//Your adapter's loadStateFlow here
adapter.loadStateFlow.
distinctUntilChangedBy {
it.refresh
}.collect {
//you get all the data here
val list = adapter.snapshot()
...
}
}
Run Code Online (Sandbox Code Playgroud)
由于我刚刚接触 Paging 库,Flow最近,这种方法可能存在缺陷,如果有更好的方法,请告诉我!
| 归档时间: |
|
| 查看次数: |
1810 次 |
| 最近记录: |