我对ViewModels中的协程感到困惑。
我的问题很简单:为什么以下协程似乎不会阻塞UIThread?(协程运行时UI仍然很平滑)
我的片段就在这里
class FragmentSeePaths : Fragment(R.layout.fragment_see_paths),
PathRecyclerAdapter.OnSetPathForWidgetListener {
private val pathViewModel: PathViewModel by activityViewModels()
private lateinit var binding: FragmentSeePathsBinding
private lateinit var listener: OnAddLineRequestListener
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
...
}
private fun observeWidgetPath() {
pathViewModel.getUserWidgetPath().observe(viewLifecycleOwner, Observer {
if (it != null) {
lifecycleScope.launch {
val times = pathViewModel.fetchBusTime(it)
updateUI(it, times)
}
}
})
}
这是带有fetchBusTime方法的简化的ViewModel:
suspend fun fetchBusTime(path: Path): Pair<List<Time>?, List<Time>?> {
Log.v("fetchBusTimeUI", Thread.currentThread().name) // Main
// Some network requests made with Retrofit
val timesResponseStartPoint: GinkoTimesResponse? = repository.getTimes(
path.startingPoint.startName,
path.line.lineId,
path.isStartPointNaturalWay
)
val timesResponseEndPoint: GinkoTimesResponse? = repository.getTimes(
path.endingPoint.endName,
path.line.lineId,
path.isStartPointNaturalWay
)
return timesResponseStartPoint to timesResponseEndPoint
}
答案 0 :(得分:1)
launch
允许我们在后台启动协程并同时继续工作。 Suspending
函数可以在不阻塞当前线程的情况下暂停当前协程的执行。我们可以在以下任何调度程序下启动协程。
为详细解释您,我以文档中的示例为例:-
fun main() {
GlobalScope.launch { // launch new coroutine in background and continue
delay(1000L)
println("World!")
}
println("Hello,") // main thread continues here immediately
runBlocking { // but this expression blocks the main thread
delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
}
}
评论应该说明一切。这将立即打印“ Hello”,并添加“ World!”一秒钟后。
这与处理您的代码相同,挂起函数fetchBusTime()
将在不阻塞线程的情况下执行,并且在此方法内完成操作后,它将执行updateUI(it, times)
。
有关此内容的更多详细信息,请阅读这篇文章here