我有一个List<Flow<T>>
,并且想生成一个Flow<List<T>>
. 这几乎是什么combine
- 除了 combine 等待每个Flow
发出一个初始值,这不是我想要的。以这段代码为例:
val a = flow {
repeat(3) {
emit("a$it")
delay(100)
}
}
val b = flow {
repeat(3) {
delay(150)
emit("b$it")
}
}
val c = flow {
delay(400)
emit("c")
}
val flows = listOf(a, b, c)
runBlocking {
combine(flows) {
it.toList()
}.collect { println(it) }
}
使用combine
(因此按原样),这是输出:
[a2, b1, c]
[a2, b2, c]
而我也对所有中间步骤感兴趣。这就是我想要从这三个流程中得到的:
[]
[a0]
[a1]
[a1, b0]
[a2, b0]
[a2, b1]
[a2, b1, c]
[a2, b2, c]
现在我有两种解决方法,但都不是很好......第一个很丑陋,不适用于可为空的类型:
val flows = listOf(a, b, c).map {
flow {
emit(null)
it.collect { emit(it) }
}
}
runBlocking {
combine(flows) {
it.filterNotNull()
}.collect { println(it) }
}
通过强制所有流发出第一个不相关的值,combine
转换器确实被调用,并让我删除我知道不是实际值的空值。对此进行迭代,更具可读性但更重:
sealed class FlowValueHolder {
object None : FlowValueHolder()
data class Some<T>(val value: T) : FlowValueHolder()
}
val flows = listOf(a, b, c).map {
flow {
emit(FlowValueHolder.None)
it.collect { emit(FlowValueHolder.Some(it)) }
}
}
runBlocking {
combine(flows) {
it.filterIsInstance(FlowValueHolder.Some::class.java)
.map { it.value }
}.collect { println(it) }
}
现在这个工作得很好,但仍然觉得我做得太过分了。协程库中是否有我缺少的方法?