【问题标题】:Collecting multiple flows into one将多个流合并为一个
【发布时间】:2021-10-31 14:49:23
【问题描述】:

我正在嵌套启动的流中从数据存储区收集数据{}。

   viewLifecycleOwner.lifecycleScope.launchWhenStarted { 
                launch { 
                    DataStore.userName.collect {
                       // it emits string value
                        Log.e(TAG, it )
                    }
                }
                launch {
                    DataStore.userPhone.collect {
                       // it emits string value
                        Log.e(TAG, it )
                    }
                }
                launch {
                    DataStore.userAddress.collect {
                       // it emits string value
                        Log.e(TAG, it )
                    }
                }
            }

有没有更好的方法来收集片段中的流?就像在单个启动块中收集所有数据一样。

【问题讨论】:

  • 使用可以使用 combine : fun <T1, T2, T3, R> combine(flow: Flow<T1>, flow2: Flow<T2>, flow3: Flow<T3>, transform: suspend (T1, T2, T3) -> R): Flow<R>。所以在这里使用combine(DataStore.userName, DataStore.userPhone, DataStore.userAddress, ::Triple).onEach{ (name, phone, address) -> .... }.launchIn(scope) - 考虑在DataStore 中添加这个作为一种方便的方法。

标签: android kotlin kotlin-coroutines kotlin-flow


【解决方案1】:

一种选择是像这样组合所有流程:

combine(DataStore.userName, DataStore.userPhone, DataStore.userAddress) { userName, userPhone, userAddress ->
    // Operate on these values
}

另一种选择是使用launchIn,它在提供的协程范围内启动流集合。

viewLifecycleOwner.lifecycleScope.launchWhenStarted { 
    DataStore.userName.onEach { userName ->
        // ...
    }.launchIn(this)

    DataStore.userPhone.onEach { userPhone ->
        // ...
    }.launchIn(this)

    DataStore.userAddress.onEach { userAddress ->
        // ...
    }.launchIn(this)
}

launchIn 只是scope.launch { flow.collect() } 的简写。

【讨论】:

  • 为了澄清,combine() 会在单个源流发出新值时从所有源流中发出当前值的新组合。这可能是想要的行为,但可能导致多个冗余操作。对于用户数据等独特的组合,zip() 可能是更好的选择。
  • @nulldroid 我们可以在多个流程中使用 zip 吗?据我所知,我们一次只能压缩两个流,flow1.zip(flow2) { a,b -> }
  • 糟糕,不知怎的,我忘记了这一点。您是对的, zip 仅适用于开箱即用的两个流程。在这种情况下,您需要做一个嵌套的 zip。 flow1.zip(flow2) { a,b -> }.zip(flow3) {ab, c -> }
  • Zip 仅在所有流发生变化时才会发出 .. 因此,例如,如果用户更改其地址,则使用 zip 运算符将不会观察到最新的地址更改。链式拉链也意味着它隐含地依赖于之前的 zip 操作,这可能会导致其他问题。 Combine 是正确的操作符,它结合了所有流中的最新流,无论它们是否独立更新。
  • 感谢所有选项,我想我会结合这三个流程。好像解决了我的问题
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 2020-03-20
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
相关资源
最近更新 更多