У меня есть List<Flow<T>>
, и я хотел бы сгенерировать Flow<List<T>>
. Это почти то, что делает 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) }
}
Теперь этот работает просто отлично, но все равно кажется, что я переусердствовал. Есть ли метод, который мне не хватает в библиотеке сопрограмм?