Kotlin协程:如何用callbackFlow实现连续trySend?
问题:Kotlin协程CallbackFlow提前关闭导致无法捕获完整回调状态
我正尝试使用Kotlin协程结合外部API处理后台任务,实现代码如下:
class SampleRepoImpl(private val readerApi: ReaderApi) : SampleRepo { override fun startReader() = callbackFlow { readerApi.searchCard(object : OnSearchCardListener { override fun onCardDetect() { trySend(ReaderState.Detect) close() } override fun onCardFound() { trySend(ReaderState.Found) close() } override fun onFinish() { trySend(ReaderState.Close) close() } }) awaitClose() } }
回调流程应为先触发onCardDetect再触发onCardFound,但当前代码中在onCardDetect内调用close()后,整个callbackFlow就会结束,无法捕获完整的回调状态。请问是否有办法让flow保持存活,直到viewModelScope取消或在特定回调(如onFinish)触发时再终止?
解决方案
核心问题是你在非终止性的回调(onCardDetect、onCardFound)中过早调用了close(),直接终止了Flow的生命周期。只需调整close()的调用时机,同时完善资源清理逻辑即可:
修改后的代码
class SampleRepoImpl(private val readerApi: ReaderApi) : SampleRepo { override fun startReader() = callbackFlow { val listener = object : OnSearchCardListener { override fun onCardDetect() { // 仅发送状态,不关闭Flow trySend(ReaderState.Detect) } override fun onCardFound() { // 仅发送状态,不关闭Flow trySend(ReaderState.Found) } override fun onFinish() { trySend(ReaderState.Close) // 仅在最终回调时关闭Flow close() } } readerApi.searchCard(listener) // 当Flow被取消(比如viewModelScope销毁)时,清理外部API资源 awaitClose { // 假设ReaderApi提供了取消搜索的方法,根据实际API调整 readerApi.cancelSearch() } } }
关键说明
- 调整
close()调用时机:只在onFinish这个表示流程结束的回调中调用close(),让Flow能接收onCardDetect→onCardFound→onFinish的完整事件序列。 - 完善资源清理:
awaitClose块中的代码会在Flow被取消时执行(比如ViewModel销毁导致viewModelScope取消),这里需要调用外部API的取消方法,避免后台任务持续运行造成内存泄漏。 - 可选优化:如果需要确保状态发送的可靠性,可以判断Channel是否活跃后再发送:
if (isActive) { trySend(ReaderState.Detect) }
内容的提问来源于stack exchange,提问作者Bitwise DEVS
相关产品推荐
相关产品推荐

