一、map&transform转换操作符
map: 对流中的每个元素应用给定的转换函数,并返回转换后的结果流(经过map内的操作后才成为结果流)。如下面为例,将Int类型转换为String类型,但这只是简单的映射函数操作,想要更复杂的处理需要使用transfor.
transform
: 是 Flow
中的一个操作符,它允许你对流中的每个元素进行转换,并且每个元素可以映射到一个新的流。而且每个输入元素可以产生零个、一个或多个输出元素(使用emit十分灵活处理,相对map也更加强大)。
二、限长操作符take
take: 从流中获取指定数量的元素,并返回一个新的流。
三、末端流操作符
如下(参考另一博主视频讲解):
以reduce为例:
四、组合操作符zip
将两个流组合成新的流
五、展平流操作符
在流进行异步接受值序列的时候,可能会 每个值都会触发对另一个值序列的请求。这样形成了一个二维Flow<Flow<Int>>(包含流的流),这时我们需要将其进行展平为单个流以进行下一步处理,集合与序列都拥有 flatten 与 flatMap 操作符来做这件事。然而,由于流具有异步的性质,因此需要不同的展平模式, 为此,存在一系列的流展平操作符。将它展开有以下模式。
1.flatMapConcat连接模式:它们在等待内部流完成之前开始收集下一个值。一个流数据完成后,再收集下一个流数据
fun requestFlow(i : Int) = flow{
emit("$i: First")
delay(500)
emit("$i: Second")
}
@Test
fun testflatMapMerge() = runBlocking {
val startTime = System.currentTimeMillis()
(1..3).asFlow()
.onEach { delay(100) }
.flatMapConcat { requestFlow(it) }
.collect{println("$it at ${System.currentTimeMillis() - startTime} ms")}
}
2.flatMapMerge并发模式
另一种展平模式是并发收集所有传入的流,并将它们的值合并到一个单独的流,以便尽快的发射值。它由 flatMapMerge 与 flattenMerge 操作符实现。比如下面先将(1.2.3)收集成一个流再合并发给另一个流,这就是并发了同一时间处理(1.2.3)这多个任务(不过将任务集合在一块)
fun requestFlow(i : Int) = flow{
emit("$i: First")
delay(500)
emit("$i: Second")
}
@Test
fun testflatMapMerge() = runBlocking {
val startTime = System.currentTimeMillis()
(1..3).asFlow()
.onEach { delay(100) }
.flatMapMerge { requestFlow(it) }
.collect{println("$it at ${System.currentTimeMillis() - startTime} ms")}
}
3.flatMapLatest
将每个源流中的元素转换为另一个流,并只关注最新转换出的流。当源流发出新元素时,如果前一个元素对应的流仍在执行,flatMapLatest
会取消前一个元素对应的流,并开始执行新元素对应的流,以确保获取到最新的结果。
fun requestFlow(i : Int) = flow{
emit("$i: First")
delay(500)
emit("$i: Second")
}
@Test
fun testflatMapMerge() = runBlocking {
val startTime = System.currentTimeMillis()
(1..3).asFlow()
.onEach { delay(100) }
.flatMapLatest { requestFlow(it) }
.collect{println("$it at ${System.currentTimeMillis() - startTime} ms")}
}
我来解释一下这里,比如1是新元素进来了,这时1的First开始执行,但需要delay(500)才执行1:Second,这个时候2作为新元素进来了,由于1:Second还没开始,还在执行,这个flatMapLatest就会取消前一个元素对应的流,来进行2的,后面一样操作,有同学可能疑问为甚3: Second at 1029 ms会输出,因为在3之后没有新元素进入了,前面的就正常进行即可