You need to enable JavaScript to run this app. 如何获取协程已销毁/取消的通知?Android全局协程清理实现
优惠活动
大模型
产品
解决方案
定价
更多

如何获取协程已销毁/取消的通知?Android全局协程清理实现

应用级协程的销毁时机感知与资源清理实现

这个需求完全可以实现,触发逻辑和callbackFlow中awaitClose的底层机制完全同源,不需要强行适配callbackFlow,就能在你现有的Application作用域协程结构里完成资源清理。

核心实现原理

  • 协程的销毁/取消是通过上下文关联的Job对象统一调度的,只要在当前协程上下文的Job上注册完成监听,就能在协程正常结束、异常终止、被主动取消的全场景下收到销毁通知
  • 这个监听的触发时机和awaitClose完全一致:awaitClose本质就是在Flow收集协程的Job上挂载完成回调,用来执行流关闭前的资源释放逻辑,直接在裸协程上挂载同样的回调,效果没有区别

适配现有代码的改造方案

只需要在注册完流监听器之后,给当前协程的Job挂上完成回调,就能实现销毁时自动执行清理:

fun doSomeWorkGlobally() {
    applicationScope.launch { // Application类作用域
        val streamListener = object : StreamListener {
            override fun dataSnapshot(data: Data) {
                dataSharedFlow.tryEmit(data)
            }
        }
        registerToListener.register(streamListener)

        // 注册协程销毁时的清理回调,触发时机和awaitClose等价
        coroutineContext[Job]?.invokeOnCompletion { cause ->
            // 仅当协程是被主动取消(对应应用作用域销毁、应用退出场景)时执行清理
            if (cause is CancellationException) {
                registerToListener.unregister(streamListener)
                // 补充其他需要释放的资源逻辑
            }
        }

        // 这里写协程长期运行的挂起逻辑,比如常驻监听、周期任务等
        // ...
    }
}

注意事项

  • 不要把清理逻辑直接写在launch代码块的末尾:因为Application作用域的协程是长期运行的,正常场景下永远不会走到代码块末尾,只有协程被取消触发销毁流程时,挂载的完成回调才会被可靠触发
  • 这个回调比直接在协程块里写finally块的可靠性更高:invokeOnCompletion是Job层面绑定的监听,不管协程块里的逻辑有没有响应取消、有没有走完,只要Job触发完成/取消状态,回调就会执行,不会因为协程内部的逻辑阻塞错过清理时机
  • 可以根据触发原因做分支判断:如果协程是因为非取消类的运行异常终止,传入的cause会是对应的异常对象,这时就不会误触发应用退出场景下的清理逻辑
  • 如果多个Repository都需要类似的协程清理逻辑,可以把回调逻辑封装成通用的Scope扩展方法,避免重复编写样板代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 12:24:04