当返回屏幕时,协程在ViewModel中被取消



我的视图模型中有以下代码:

viewModelScope.launch {
val response = request.invoke(coroutineScope)
responseBlock?.invoke(response)
}.apply {
invokeOnCompletion {
Log.e("Cancellation", "2---", it)
if (showLoading) {
loadingCount--
changeLoadingIfNeeded()
}
}
}

我正在使用jetpack navigator,它在第一次创建屏幕时工作得很好,但是当我转到另一个屏幕并回到这个屏幕时,协程被取消,并显示以下消息kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelled}@545aaed。为什么会发生这种情况,我该如何避免?

如果你不希望你的协程在Fragment或Activity被销毁时被取消,你必须将它们从Fragment、Activity或ViewModel的生命周期中解放出来。对于这种情况,您可以创建一个新的协程范围来启动;例如:

CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
val response = request.invoke(coroutineScope)
responseBlock?.invoke(response)
}

如果你想在协程中做UI操作,有一个快捷函数,它与上面的相同,唯一的区别是Dispatchers.Main:

MainScope().launch {
val response = request.invoke(coroutineScope)
responseBlock?.invoke(response)
}

请记住,如果你不够小心,你还会遇到其他问题。由于协程的生命周期已经结束,如果您正在执行UI操作,则需要手动检查以下内容:

  1. 您要更改的视图是否仍然存在?
  2. 这个片段还存在吗?
  3. 活动是否仍然存在?

尽量不要在协程中保留任何Fragment或Activity的引用;如果必须的话,一定要使用WeakReference。

修改

private val viewModel: MainViewModel by viewModel()

private val viewModel: MainViewModel by inject()

PS:我使用koin作为依赖注入器

相关内容

  • 没有找到相关文章

最新更新