【问题标题】:Cancel all Kotlin coroutines pending jobs on ViewModel's onCleared()取消 ViewModel 的 onCleared() 上所有待处理的 Kotlin 协程
【发布时间】:2019-09-01 14:52:11
【问题描述】:

在活动完成后在 ViewModel 的 onCleared() 中停止 jobs 会显示 JobCancellationException: Job is being cancelled 并保持应用程序冻结崩溃:

从 Android 中的 ViewModel 的 onCleared() 取消所有 kotlin 协程待处理作业的正确方法是什么

我在 viewModel 中的代码:

private val job = SupervisorJob()
private val uiScope = CoroutineScope(Dispatchers.Main + job)

 uiScope.launch {
        try {
            repeat(152212000001) { it ->
                try {
                    Log.d("Timer : ", it)
                    delay(1000)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        } catch (e: CancellationException) {
            e.printStackTrace()
        }
    }

ViewModel 内部:

override fun onCleared() {
    job.cancel()
    super.onCleared()
}

【问题讨论】:

    标签: android kotlin kotlin-android-extensions kotlin-extension kotlin-coroutines


    【解决方案1】:

    根据Easy Coroutines in Android: viewModelScope blog post

    viewModelScope 通过向 ViewModel 类添加 extension property 来贡献structured concurrency,该类在 ViewModel 被销毁时自动取消其子协程。

    因此,通过添加对androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0-alpha02(或更高版本)的依赖,您将能够默认使用viewModelScope 来做正确的事情:

    viewModelScope.launch {
        repeat(152212000001) { it ->
            Log.d("Timer : ", it)
            delay(1000)
        }
    }
    

    【讨论】:

    • 感谢您的回答。实际上,我能够取消协程作业,但无法取消长流程子作业。那么,视图模型销毁后是否立即取消子协程?
    • 是的,这就是结构化并发的重点。只要您不通过在 GlobalScope 等其他范围内启动协程而搞砸,它们将注册为 viewModelScope 的子级并递归取消。
    猜你喜欢
    • 2019-04-12
    • 1970-01-01
    • 2018-07-12
    • 2015-11-25
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多