Kotlin 系列之Flow (三)执行顺序
Hello I`am Flow Welcome to Flow Unit 3
这次来聊聊,Flow 的执行顺序 与 执行优化
Flow 的执行顺序
对于Flow的收集操作来说 ,他是运行在调用终止操作的那个协程上,默认情况下 它是不会启动新的协程。
每发射一次 emit 发射的元素都会 经历所有的中间操作,最后在 终止操作被处理。(MD 就是从上到下走一遍)
Example
fun main() = runBlocking {
(1..3).asFlow()
.filter{
println("filter $it")
it % 3 ==0
}.map {
println("map $it")
it
}.collect{
println("collect $it")
}
}
打印结果:
filter 1
filter 2
filter 3
map 3
collect 3
Flow 的收集动作总是 发生在调用协程的上下文当中。
也就是 终止操作 在 A处调用,A 所处的协程就将是 Flow内容执行所处的协程(默认情况)
要是不想 让它们在同一个协程执行可以么?(可以,但是。。。)
private fun myMethod():Flow<Int> = flow{
kotlinx.coroutines.withContext(Dispatchers.Default){
for (i in 1..4){
Thread.sleep(1000)
emit(i)
}
}
}
fun main() = runBlocking {
myMethod().collect{ println(it)}
}
run 了之后,发现抛异常了。。。(发射时的协程 于 收集时的协程 不是同一个,臣妾办不到啊)
啊?。。。
flowOn 来了
也就是说 终止操作 在 A处调用,不使用 A 所处的协程,使用自身指定的协程。(不好意思啊A,我有对象了)
private fun myMethod():Flow<Int> = flow{
kotlinx.coroutines.withContext(Dispatchers.Default){
for (i in 1..4){
Thread.sleep(1000)
emit(i)
}
}
}.flowOn(Dispatchers.Default) // <<<<======= 在这里 指定执行协程
fun main() = runBlocking {
myMethod().collect{ println(it)}
}
Buffer 优化
在执行 终止操作 期间,发射阶段 也不要空闲下来,去做一些缓存操作,从而节省时间
(不要等到盘子空了,才开始做下一道菜)
private fun myMethod():Flow<Int> = flow{
for (i in 1..4){
delay(100)
emit(i)
}
}
fun main() = runBlocking {
val time = measureTimeMillis {
myMethod().buffer() //<<<<==== 在这里
.collect{
delay(200)
println(it)
}
}
println(time)
}
本节小结: 介绍了Flow 的执行顺序和 flowOn 与 Buffer 作用 下一节 Flow(四)组合与实践
————————————————
版权声明:本文为CSDN博主「翻滚吧章鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_37558974/article/details/120113554