Kotlin协程收集callbackFlow时被取消,后续代码不执行如何解决?
问题触发原因
该问题不是协程被取消,而是collect操作被永久挂起导致后续逻辑无法执行:
callbackFlow提供的awaitClose()是挂起函数,作用是持续监听Flow的关闭事件,仅当Flow被主动调用close()、或者上下游协程被取消时,awaitClose()才会结束挂起状态并返回。- 你提供的代码中,
callbackFlow内调用trySend发送数据后,直接进入awaitClose等待逻辑,但全程没有任何逻辑主动关闭该Flow,因此innerFlow().collect会一直处于挂起状态,永远不会执行完成,后续的println("Bye, world!")自然没有执行机会。
修复方案
根据实际业务场景可选择以下任意一种修改方式:
方案1:发送完单条数据后主动关闭Flow
如果该Flow仅需要发送一次数据就结束,在trySend之后直接调用close()即可触发awaitClose返回:
suspend fun innerFlow() = callbackFlow { trySend("U r world?") close() // 主动关闭Flow,结束awaitClose挂起 awaitClose { } }
方案2:替换为更适配当前场景的Flow实现
当前场景不需要将第三方回调转为Flow的能力,直接用flowOf实现更简单,无需手动处理关闭逻辑:
// 直接替换innerFlow的实现即可 fun innerFlow() = flowOf("U r world?")
方案3:回调场景下在结束节点触发关闭
如果确实需要用callbackFlow封装第三方回调,在回调的结束/销毁时机调用close()即可:
suspend fun innerFlow() = callbackFlow { val customCallback = object : CustomCallback { override fun onDataReceived(data: String) { trySend(data) } override fun onAllDataSent() { close() } // 所有数据发送完成时关闭Flow override fun onError(e: Throwable) { close(e) } // 异常时关闭Flow } registerCallback(customCallback) awaitClose { unregisterCallback(customCallback) } }
上述任意一种方案修改后,运行代码即可输出你预期的全部日志。
内容的提问来源于stack exchange,提问作者Ji Sungbin
相关产品推荐
相关产品推荐

