android 返回屏幕时在ViewModel中取消协同程序

vlju58qv  于 2023-01-11  发布在  Android
关注(0)|答案(2)|浏览(178)

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

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。为什么会发生这种情况,我如何避免?

rslzwgfq

rslzwgfq1#

如果你不希望在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.您试图更改的视图是否仍然存在?
1.碎片还存在吗?
1.活动是否仍然存在?
尽量不要在你的协程中保留任何片段或活动的引用;如果必须这样做,请始终使用WeakReference。

y1aodyip

y1aodyip2#

我通过改变来修复

private val viewModel: MainViewModel by viewModel()

private val viewModel: MainViewModel by inject()

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

相关问题