kotlin - 等待循环中的所有流程完成

标签 kotlin kotlin-coroutines kotlin-flow

我有一个按流返回数据的 API:

suspend fun loadData(...): Flow<List<Items>> 
suspend fun loadDetails(...): Flow<ItemDetails>

当我获取数据时,我需要加载一些项目的详细信息并将结果转换为实时数据:

job = SupervisorJob()
val context = CoroutineScope(job + Dispatchers.Main.immediate).coroutineContext
liveData(context = context) {
  emitSource(
        api.loadData(...)
           .flatMapConcat { items ->
              items.forEach { item -> 
                 if (item is Details){
                    api.loadDetails(item).flatMapConcat{ details ->
                        item.details = details
                    }
                 }
              }
             flow {
               emit(items)
             }
            }
   ) 

此处的问题是 emit(items)loadDetails 完成之前调用,因此调用了较新的 item.details = details

如何等待forEach更新所有项目?

最佳答案

好吧,我在这里做了一些假设,所以如果我有任何错误,请在评论中纠正我,我会更新我的答案。

一般来说,如果您不是绝对需要的话,不鼓励使用 flatMapConcat (它实际上写在函数的文档中)

我假设loadDetails可以简单地表示为如下所示:

suspend fun loadDetails(item: Details) = flow<Any>{
    emit(Loading()) // some sort of sealed wrapper class
    val value = someAsyncOperation()
    emit(Success(value))
}

现在我们定义一个简单的辅助函数来获取 loadDetails 发出的第一个 Success

suspend fun simplerLoadDetails(item: Details): Any { 
    // this will collect items of the flow until one matches the lambda
    val wrappedSuccessValue = loadDetails(item)
        .first { it is Success } as Success 
    return wrappedSuccessValue.value
}

还有一个来处理整个列表

suspend fun populateDetails(items: List<Any>) {
    items.forEach {
        if (it is Details) {
            it.details = simplerLoadDetails(it)
        }  
    }

}

此处注意:如果您需要并行使用,这将按顺序处理所有元素

suspend fun populateDetails(items: List<Any>) {
    coroutineScope {
        items.forEach {
            if (it is Details) {
                launch {
                    it.details = simplerLoadDetails(it)
                }  
            }
        }
    }
}

现在,对于 loadData 发出的每个元素列表,我们需要做的就是调用 populateDetails

suspend fun itemsWithDetails(...) = loadData(...)
    .onEach { itemsList ->
        populateDetails(itemsList)
    }

关于kotlin - 等待循环中的所有流程完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63129264/

相关文章:

Kotlin 多平台 : kotlinx. coroutines.test 库在 commonTest 模块中不可见

kotlin-coroutines - koltin,直接使用CoroutineScope和从CoroutineScope派生类有什么区别

android - Kotlin Flow - callbackFlow 的替代品

android - Kotlin 协程 Flow 中 RxJava Observable 和 FlatMap 的等价物是什么

kotlin - 在不可空字段中测试驱动的最佳方法

Kotlin 初始化 : how to fail

android - 如何在 Android 上停止 Kotlin 协程?

Kotlin 从 generateSequence() 到 flow() ,但生成了错误的字节码

android - "Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.16"

android-studio - 安卓工作室 : Adding a dependency that the IDE cannot download for itself