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

Kotlin中如何等待异步任务完成后返回正确结果?

解决方案

1. 将回调式异步函数转为挂起函数

你的getUserFromDatabase是回调风格的异步方法,首先需要把它包装成协程挂起函数,才能在协程中以同步方式调用:

// 包装原有回调方法为挂起函数
suspend fun getUserFromDatabase(id: String): User {
    return suspendCoroutine { continuation ->
        getUserFromDatabase(id) { user ->
            // 异步任务完成后恢复协程,返回结果
            continuation.resume(user)
        }
    }
}

2. 修改getUsersList为挂起函数,等待所有任务完成

使用async启动并行协程任务,通过awaitAll等待所有任务结束后返回完整列表:

suspend fun getUsersList(userIds: List<String>): List<User> {
    return coroutineScope {
        // 为每个userId启动异步任务
        userIds.map { id ->
            async { getUserFromDatabase(id) }
        }.awaitAll() // 等待所有任务完成,返回结果集合
    }
}

这里的coroutineScope是结构化并发的核心,它会确保所有子协程执行完毕后再结束作用域,若任一子协程失败,所有子协程都会被取消,避免协程泄漏。

3. 构建Type1到User的映射Map(针对补充需求)

同样用协程并行处理,最终返回完整的映射关系:

suspend fun buildType1ToUserMap(type1List: List<Type1>): Map<Type1, User> {
    return coroutineScope {
        // 先为每个Type1创建对应的异步任务
        val deferredMap = type1List.associateWith { type1 ->
            async { getUserFromDatabase(type1.userId) }
        }
        // 等待所有任务完成,转换为最终的Map
        deferredMap.mapValues { (_, deferred) -> deferred.await() }
    }
}

4. 调用挂起函数的正确方式

挂起函数不能在普通函数中直接执行,需要在协程作用域内调用。比如在ViewModel中使用viewModelScope,在Activity/Fragment中使用lifecycleScope:

class MyViewModel : ViewModel() {
    fun loadData(type1List: List<Type1>) {
        viewModelScope.launch {
            // 等待获取完整用户列表
            val userList = getUsersList(type1List.map { it.userId })
            // 等待构建完成Type1与User的映射
            val type1UserMap = buildType1ToUserMap(type1List)
            
            // 此处更新ViewModel状态,通知UI刷新
        }
    }
}

关键注意点

  • 禁止在UI线程使用runBlocking调用挂起函数,这会阻塞UI导致卡顿
  • async用于并行处理独立异步任务,比串行循环效率更高
  • 结构化并发(coroutineScope)确保所有子任务被正确管理,杜绝协程泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:40:10