【发布时间】:2021-01-06 06:23:24
【问题描述】:
我正在使用 Kotlin flow 和 Android Paging 3 库编写一个玩具 Android 应用程序。该应用程序调用一些远程 API 来获取照片列表,并使用 RecyclerView 和 PagingDataAdapter 显示它们。
我发现pagingAdapter.submitData()后面的代码没有执行。
这里是sn-p的代码(这个函数在Fragment中):
fun refreshList() {
lifecycleScope.launch {
photosViewModel.listPhotos().collect {
// `it` is PagingData<Photo>
pagingAdapter.submitData(it)
Log.e(TAG, "After submitData")
}
}
}
日志After submitData没有打印出来。
但是,如果我将日志记录放在 pagingAdapter.submitData() 行的前面,则会打印出来,如下所示:
fun refreshList() {
lifecycleScope.launch {
photosViewModel.listPhotos().collect {
// `it` is PagingData<Photo>
Log.e(TAG, "Before submitData")
pagingAdapter.submitData(it)
}
}
}
日志Before submitData打印没有问题。
请问为什么会这样?
【问题讨论】:
-
如果对 collect 的调用是在后台线程上,我会假设 submitData(it) 需要很长时间才能完成,在日志之前和之后添加一个断点,然后检查你是否打两个。另一个想法是在 submitData 上添加断点并进入该方法,看看是什么花了这么长时间
-
在协程范围内有
pagingAdapter.submitData(it)的原因是什么?这是 UI 相关的,因此您应该考虑不要在协程中运行它。您正在获取的数据可以使用协程从 UI 线程中获取,但结果应该在Dispatchers.Main上发出(在您的 viewModel 中)。您应该考虑将您的Flow映射到LiveData -
@ChristianB OP 的代码完全在 UI 线程上运行。
lifecycleScope.coroutineContext[ContinuationInterceptor] == Dispatchers.Main -
@ChristianB 因为
submitData是一个挂起函数。它必须在协程范围内。 -
@seemuch 我不知道
submitData是一个挂起函数。那么它是有道理的。谢谢
标签: android kotlin kotlin-coroutines android-paging android-paging-library