android - Kotlin flow inside flow,父流不调用collect

标签 android kotlin kotlin-coroutines kotlin-flow

最近我发现了一个我无法理解的流行为。

问题描述

考虑这种情况: 你有一个父 flow 并且在它的 collect 中,你将有一个“子”flow 并调用 .collect(),像这样:

parentFlow.collect {
    childFlow.collect()
}

然后,如果 parentFlow 发出一些值,则不会调用 childFlow.collect()

我尝试过的

通过在 SO 上进行一些搜索,我发现以下问题与我的类似:

  1. Android: collecting a Kotlin Flow inside another not emitting
  2. Chaining Flows (collecting a Flow within the collect{} block of another Flow)

但是我打算更深入地挖掘这种行为背后的原因,因此我创建了一个项目来可靠地重现它,您可以在 github 上查看它: https://github.com/dumbfingers/Playground/tree/flow-inside-flow

在这个迷你重现中,我放了一些日志输出。当你点击按钮时,预期的日志输出应该是:

Test: onArrayUpdated
Test: item: {some number}
Test: item: {some number}
Test: onFlowChanged
Test: repoObserve delayed
Test: item: {some number}
Test: item: {some number}
Test: repoAnotherObserve delayed

然而,实际结果是:

Test: onArrayUpdated
Test: item: {some number}
Test: item: {some number}

这表明 randomFlow 中的这两个 collect 调用没有被调用:

      repository.repoObserve(list).collect {
            repository.repoAnotherObserve().collect()
        }

问题

在这个 SO 中:Android: collecting a Kotlin Flow inside another not emitting 答案表明“收集无限流量”导致了这个问题。

在我的实验中,要么

  • repoObserverepoAnotherObserve 更改为 suspend 方法并使它们不返回流

  • 使用combine 组合这些流

将解决这个问题。

但为什么另一个流的收集中的收集流不起作用?

最佳答案

您可以在父 collect { ... } block 中启动协程

val scope: CoroutineScope = ...
parentFlow.collect {
    scope.launch {
        childFlow.collect()
    }
}

parentFlow.flatMapMerge { childFlow }.collect {
    // logic here ...
} 

您还可以将 flatMapMerge 替换为 flatMapLatest/flatMapConcat/flatMapFirst (FlowExt 图书馆)

希望能帮到你

关于android - Kotlin flow inside flow,父流不调用collect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71615847/

相关文章:

java - 导致构建错误的 Android Intent setType 和 addCategory 方法

android - RecyclerView 后让空 View 占用剩余空间?

android - 垂直方向的 Recyclerview 在屏幕水平滚动时上下滚动

java - WAR 文件 : Could not find or load main class, 但它在那里

android - 收集服务中的流

android - 有流的房间在空时返回 null

android - 扩展 RecyclerView : Error Inflating Class com. example.MyRecyclerView

java - 我如何在 Kotlin 中编写 Java 括号 "[ ]"?

android - 挂起函数会挂起协程吗?

Android - 无法使用编辑文本字符串的过滤结果更新 ListView