如何将Kotlin流分成2个流?

时间:2019-09-05 14:19:20

标签: android kotlin kotlin-coroutines

我正在尝试学习协程,但仍然存在一些基本问题。 我有一个发出一系列项目的流,我想将流分成2个流。这就是我用RxJava编写的方式:

    val list = Flowable.just(1..6).share()
    val even = list.filter { it % 2 == 0 }.subscribe { println(it) } // 2, 4, 6
    val odd = list.filter { it % 2 == 1 }.subscribe { println(it) } // 1, 3, 5

我该如何用Kotlin协程流复制它?预先感谢。

3 个答案:

答案 0 :(得分:3)

一系列sharing operators(以及a hot SharedFlow)正在简化您正在寻找的工作流程(使用Kotlin Flows)。

同时,流量自然是冷的(因此您不能真正地按原样共享),但是它们仍然可以共享热源来满足您的需求。我提供了有关如何in this answer的详细信息。

简而言之,最终结果如下:

val original: Flow<String> = flowOf("aap", "noot", "mies", "wim", "zus","jet","weide","does")

// create an implicit hot BroadcastChannel, shared between collectors
// so that they each get all elements (which are each produced only once)
val sharedFlow = original.broadcastIn(scope).asFlow()

// create derived cold flows, which will subscribe (on collect) to the
// same hot source (BroadcastChannel)
val flow1 = sharedFlow.filter { it.length == 4 }
val flow2 = sharedFlow.filter { it.length == 3 }.map { it.toUppercase() }

flow1.collect { it -> println("Four letter: ${it}") }
flow2.collect { it -> println("Three letter: ${it}") }

(很快将由SharedFlow代替。)

答案 1 :(得分:2)

对于科特林流量,您对Rx所做的操作几乎是不可能的,因为在您的示例中,share()将创建可热观测,而科特林的流量自然而然

您可以改用Channel,因为它们代表了Kotlin中的热门流

我从 Roman Elizarov 阅读了有关Cold flows, hot channels的博客文章。

答案 2 :(得分:1)

@shkschneider是完全正确的。这是完整的示例:

import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking

@ExperimentalCoroutinesApi
fun main() {
    runBlocking {
        val flow = flow {
            for (i in 1..10) {
                emit(i)
            }
        }
        flow.filter { it % 2 == 0 }.collect { println(it) } // prints 2 4 6 8 10
        flow.filter { it % 2 != 0 }.collect { println(it) } // prints 1 3 5 7 9
    }
}