簡體   English   中英

Kotlin 流內流,父流不調用collect

[英]Kotlin flow inside flow, the parent flow does not call collect

最近我發現了一個我無法理解的流行為。

問題描述

考慮這種情況:您有一個父flow ,在其collect內部,您將有一個“子” flow並調用.collect() ,如下所示:

parentFlow.collect {
    childFlow.collect()
}

然后,如果 parentFlow 發出一些值,則不會調用childFlow.collect()

我試過的

通過對 SO 進行一些搜索,我發現以下問題與我的類似:

  1. Android: 收集一個 Kotlin 流在另一個不發出
  2. 鏈接流(在另一個流的 collect{} 塊中收集一個流)

但是我打算更深入地了解這種行為背后的原因,因此我創建了一個項目來可靠地重現它,您可以在 github 上查看:https://github.com/dumbfingers/Playground/tree/flow-inside -流

在這個迷你重現中,我放了一些日志 output。當你點擊按鈕時,期望日志 output 應該是:

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組合這些流

將解決這個問題。

但是為什么另一個流的收集中的收集流不起作用?

您可以在 parent collect {... } 塊中啟動協程

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

或者

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

您還可以將flatMapMerge替換為flatMapLatest / flatMapConcat / flatMapFirstFlowExt庫)

希望能幫到你

每次單擊時,您的點擊偵聽器都會生成完全相同的兩個數字數組列表,因為您使用的是每次都具有相同種子值 10 的新 Random 實例。 您將它們傳遞給 StateFlow,並且 StateFlow 具有與distinctUntilChanged()相同的行為。 它們不會發出與上次發出的值相等的值。

我想如果你從你的隨機構造函數調用中刪除參數,你會得到你預期的 output。這是因為你最里面的調用流不像你鏈接的問題那樣是無限的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM