You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

返回页面时ViewModel中协程被取消的原因及解决方法

问题:Jetpack Navigator返回后ViewModel协程被取消报错

在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。

原因分析

问题出在request.invoke(coroutineScope)这一行:你传入的coroutineScope大概率是页面(如Fragment)的生命周期Scope(比如lifecycleScope)。当通过Jetpack Navigator跳转到其他页面时,原页面的Fragment会进入STOPPED状态,其生命周期Scope会被系统自动取消,导致该Scope下的协程(即request内部执行的逻辑)被终止。而viewModelScope的生命周期与ViewModel绑定,只要ViewModel未被销毁(页面跳转返回时ViewModel通常仍存活),该Scope下的协程会继续运行。返回页面后,之前启动的viewModelScope协程尝试继续执行,但内部依赖的已取消协程会触发JobCancellationException。

解决方案

方案一:替换为ViewModel的Scope(推荐)

将传入request的协程Scope改为ViewModel自身的viewModelScope,确保协程生命周期与ViewModel绑定,不受页面跳转影响:

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

方案二:基于页面生命周期重新触发请求

如果request必须依赖页面的生命周期逻辑,可在页面(Fragment)的onResume方法中重新触发该请求,确保使用当前活跃的页面生命周期Scope:

  1. 在ViewModel中暴露触发请求的方法:
fun fetchData(pageScope: CoroutineScope) {
    viewModelScope.launch {
        val response = request.invoke(pageScope)
        responseBlock?.invoke(response)
    }.apply {
        invokeOnCompletion {
            Log.e("Cancellation", "2---", it)
            if (showLoading) {
                loadingCount--
                changeLoadingIfNeeded()
            }
        }
    }
}
  1. 在Fragment的onResume中调用:
override fun onResume() {
    super.onResume()
    viewModel.fetchData(lifecycleScope)
}

内容的提问来源于stack exchange,提问作者aloj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:05:32