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

Job.cancel()无法取消协程的问题及Retrofit/Room调用时的取消疑问

Job.cancel()无法取消协程的问题及Retrofit/Room调用时的取消疑问

我先还原下你的测试场景哈,你写了个Repository类,用delay(3000)模拟API请求的延迟,然后尝试用cancel()方法取消协程:

class Repository {
    var job: Job? = null
    fun getAll() {
        job = CoroutineScope(Dispatchers.IO).launch {
            try {
                delay(3000)
                println("getAll oke")
            } catch (e: Exception) {
                println("CancellationException")
            }
        }
    }

    fun cancel() {
        job?.cancel()
        println("cancel")
    }
}

fun main() {
    runBlocking {
        val api = Repository()
        launch {
            api.getAll()
        }
        delay(1000)
        api.cancel()
        delay(5000)
        println("END")
    }
}

这段代码的输出是:

cancel
CancellationException
END

但如果把delay(3000)换成Thread.sleep(3000),输出就变成了:

cancel
getAll oke
END

你已经摸透了核心原因:delay() 是可取消的挂起函数,它会主动检查协程的取消状态,一旦检测到协程被取消,就会抛出CancellationException终止协程;而Thread.sleep() 是阻塞线程的普通方法,完全感知不到协程的存在,自然不会响应取消请求,所以哪怕调用了cancel(),协程里的代码还是会跑完。

接下来重点解答你的疑问:如果getAll()里是Retrofit或者Room的调用,调用cancel()能取消这些操作吗?

答案是:可以的,只要用官方适配协程的挂起函数方式调用。

  • 对于Retrofit:从2.6.0版本开始,官方原生支持挂起函数接口,比如你定义的API接口是这样的:

    interface ApiService {
        @GET("data")
        suspend fun fetchData(): Response<Data>
    }
    

    这种挂起函数版本的请求是支持协程取消的。当你调用job.cancel()时,Retrofit会自动取消底层的OkHttp请求,协程也会随之终止,不会继续执行后续代码。

  • 对于Room:Room同样支持挂起函数,比如Dao里的查询方法定义成挂起函数:

    @Dao
    interface DataDao {
        @Query("SELECT * FROM data")
        suspend fun getAllData(): List<Data>
    }
    

    这种挂起函数的数据库操作也是可取消的,当协程被取消时,Room会终止当前的查询操作,协程也会停止执行。

它们能被取消的原因是:Retrofit和Room的挂起函数内部都实现了可取消的逻辑,会在合适的时机检查协程的取消状态,就像delay()一样,一旦检测到取消就抛出异常终止协程,同时终止底层的网络请求或数据库操作。

不过要注意:如果用的是Retrofit的Call异步回调方式(非挂起函数),或者Room的非挂起函数+RxJava/Callback的方式,那协程的cancel()就无法直接取消这些操作了,必须手动管理请求的取消(比如调用Call的cancel方法)。

备注:内容来源于stack exchange,提问作者Nguyễn Mạnh Cường

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:29:49