请尝试分析下列代码实际输出情况,以此来理解mapLatest操作符,这个流末端操作符还是非常有用的,举个例子来说,比如用户一直滑动鼠标,而你希望鼠标滑动时根据鼠标位置刷新某个东西,但如果你侦测鼠标事件刷新的话,那就太频繁了,所以你希望用户滑动过程中如果停顿一下再去刷新(可能这样也不是最好,下回说其它操作符)
@Test
fun testMapLatest(){
runBlocking {
flow {
emit("a")
delay(100)
emit("b")
delay(100)
emit("c")
delay(220)
emit("d")
delay(400)
emit("e")
emit("f")
}.mapLatest { value ->
println("Started computing $value")
delay(200)
"Computed $value"
}.collect{
println("last result===>$it")
}
}
}
正确的解释:
mapLatest操作符理解,当上游流中的某个元素持续一定时间不改变则会最终放入下游流
这个一定时间指的就是mapLatest操作符中delay的时间,上例是delay(200), 还有就是上游流中的最后一个元素(f)必然会被放入下游流中
那么根据这个规则 c, d, f将会被放入流中,因为c,d持续时间足够长, f是最后一个
这个末端操作符和collectLatest规则是一样的,可自行试试它。
在来看其它几个常用的末端操作符,实际上我在官方安卓组织架构的demo中见到最多的就是这个mapLatest,其它的感觉有用,但实际中好像确实不太能用的到, 想象的挺好的,但实际就是不太有出场机会, 除非刻意去创造这个机会。
比如 map, first, last, single, conflate等等 有很多,自己研究研究,都不难理解了。 我之所以说这个mapLatest,就是因为我在安卓的标准架构工程demo那个什么sun-flower中看到它多次出场。
我认为可能很有的conflate也说一下吧
/**
* conflate我们在其它语言中有叫做防抖动的,说白了就是控制节奏
* 不管上游流怎么折腾,我下游流就是不断的按部就班的取上游流当前的最后一个
* 当然我会保证第一个和最后一个一定被取到(这非常有必要), 你使用conflate时下游流 必然
* 要有个delay(x), 不然等于没用它一样,毫无意义。 理解为在单位x时间内上游流产生的值会被忽略掉即可
*/
@Test
fun testConflate(){
val f = flow {
for( i in 1..10){
delay(100)
emit(i)
}
}
runBlocking {
f.conflate().collect{
delay(300)
println(it)
}
}
}
1
3
6
9
10
网友评论