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

将suspendCancellableCoroutine转为callbackFlow及重复调用报错解决

问题原因分析

你用suspendCancellableCoroutine实现的函数报错,核心原因是**continuation.resume()只能调用一次**,但你的Callback可能被多次触发(比如重复调用result()时未清理旧的callback,或者每次调用都注册新callback导致重复回调),多次尝试resume同一个continuation就会抛出"Already resumed"异常。

正确的callbackFlow实现及调用方式

1. 修正result()函数

用callbackFlow时,必须在流关闭时注销callback,避免内存泄漏和重复回调:

suspend fun result() = callbackFlow<Int> {
    val callback = object : Callback {
        override fun onResult(value: Int) {
            // 用trySend发送结果,适配callback可能运行在非协程线程的场景
            trySend(value).run {
                if (!isSuccess) {
                    // 可选:处理发送失败(比如流已关闭)
                }
            }
        }
    }

    // 注册callback到你的目标服务/SDK
    someApi.registerCallback(callback)

    // awaitClose会在流结束时执行,这里务必注销callback
    awaitClose {
        someApi.unregisterCallback(callback)
    }
}

2. 协程中调用的两种场景

场景1:只需要单次结果(和原代码行为一致)

用first()获取第一个回调结果后自动关闭流,同时注销callback:

someCoroutine {
    val result = result().first()
    when(result) {
        x -> doSomething()
        y -> doSomethingElse()
        // ...其他分支
    }
}

场景2:需要接收多次回调结果

用collect()持续监听回调,直到流被取消或主动关闭:

someCoroutine {
    result().collect { value ->
        when(value) {
            x -> doSomething()
            y -> doSomethingElse()
            // ...其他分支
        }
    }
    // collect是挂起函数,会一直阻塞直到流关闭
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:01:06