Kotlin如何将回调式连接方法封装为挂起协程实现异步等待
Kotlin回调转协程封装实现方案
完全可以实现,Kotlin协程原生支持将传统回调式API转换为挂起函数,你可以通过suspendCancellableCoroutine完成需求,具体实现如下:
步骤1:改造B类的connect方法为挂起函数
首先将原有回调逻辑包裹在suspendCancellableCoroutine中,当连接成功回调触发后再恢复协程执行,保证后续代码拿到最新的连接状态:
class B { // 注意原代码中isConnected是只读val,需要改为可写var才能修改值 var isConnected: Boolean = false // 声明为挂起函数 suspend fun connect() = suspendCancellableCoroutine<Unit> { continuation -> someObject.connect(object : SomeListenerInterface { override fun onSuccess() { isConnected = true // 连接成功,恢复协程执行 continuation.resume(Unit) } // 若原有监听支持失败回调,同步添加异常处理逻辑 override fun onError(error: Exception) { // 连接失败,抛出异常给上层调用方处理 continuation.resumeWithException(error) } }) } }
步骤2:改造A类的connect方法
因为调用了挂起函数,A类的connect方法可以声明为挂起函数,保证执行顺序严格同步:
class A { // 声明为挂起函数,保证执行顺序 suspend fun connect() { // 此处会挂起,直到B类connect的成功/失败回调触发后才会往下执行 classB.connect() // 此时拿到的isConnected一定是回调更新后的最新值 val isConnected = classB.isConnected // 后续业务逻辑 } }
可选适配场景
- 如果你不希望A的connect方法是挂起函数,可以在指定协程作用域(比如Android的
viewModelScope、lifecycleScope)中启动协程调用:
// 传入你项目中合适的协程作用域 fun connect(coroutineScope: CoroutineScope) { coroutineScope.launch { classB.connect() val isConnected = classB.isConnected } }
- 可以添加超时逻辑避免协程无限挂起:
suspend fun connect() { // 5秒超时,超时会抛出TimeoutCancellationException,可按需捕获处理 withTimeout(5000) { classB.connect() } val isConnected = classB.isConnected }
注意:使用前需要确保项目已经引入kotlinx-coroutines-core相关依赖。
内容的提问来源于stack exchange,提问作者StackerSapper
相关产品推荐
相关产品推荐

