如何获取协程已销毁/取消的通知?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
相关产品推荐
相关产品推荐

