持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
展平流
处理包含流的流,将其展平为单个单位进行下一步处理。
flatMapConcat:按顺序收集流,处理流flatMapMerge:顺序调用代码块,并发收集结果流flatMapLatest:展平模式的collectLatest
fun requestFlow(i:Int):Flow<String> = flow {
emit("$i : First")
delay(500)
emit("$i : Second")
}
fun main() = runBlocking<Unit> {
(1..3).asFlow().map { testFlow.requestFlow(it) }
.collect { println("map:$it") }
(1..3).asFlow().flatMapConcat { testFlow.requestFlow(it) }
.collect { println("flatMapConcat:$it") }
(1..3).asFlow().flatMapMerge { testFlow.requestFlow(it) }
.collect { println("flatMapMerge:$it") }
}
map:kotlinx.coroutines.flow.SafeFlow@27ddd392
map:kotlinx.coroutines.flow.SafeFlow@19e1023e
map:kotlinx.coroutines.flow.SafeFlow@7cef4e59
flatMapConcat:1 : First
flatMapConcat:1 : Second
flatMapConcat:2 : First
flatMapConcat:2 : Second
flatMapConcat:3 : First
flatMapConcat:3 : Second
flatMapMerge:1 : First
flatMapMerge:2 : First
flatMapMerge:3 : First
flatMapMerge:1 : Second
flatMapMerge:2 : Second
flatMapMerge:3 : Second
flatMapLatest:1 : First
flatMapLatest:2 : First
flatMapLatest:3 : First
flatMapLatest:3 : Second
流异常
当流发射器带有异常时,流收集器可以使用try/catch来处理异常,捕获在发射器、过渡流操作符或末端操作符中发生的异常。捕获异常后收集器便会停止收集值。
try {
(1..5).asFlow().collect { value ->
println(value)
check(value < 3) { //当value>=3抛出异常,停止收集
"Collected $value"
}
}
} catch (e: Throwable) {
println("Caught $e")
}
1
2
3
Caught java.lang.IllegalStateException: Collected 3
流必须保证异常透明性。发射器可以使用catch操作符来保留异常的透明性,如果在构造器内使用try/catch处理异常,发射器的异常无法被收集器收集。同样,也是捕获异常后停止收集值。
catch仅捕获上游流异常,下游流的异常会逃逸。 处理方法:将collect操作符中的动作放到onEach操作符中,并将其放到catch操作符之前。这样就可以不使用try/catch捕获所有的异常。
(1..5).asFlow()
.onEach { value ->
check(value < 3) { //当value>=3抛出异常
"Collected $value"
}
println(value)
}
.catch { cause -> cause?.let { println(it) } } //对异常进行处理
.collect()
1
2
java.lang.IllegalStateException: Collected 3
流完成
流可以通过命令式或声明式显示收集完成。
- 命令式:
try/finally
try {
(1..3).asFlow()
.collect { println(it) }
}finally {
println("Done")
}
1
2
3
Done
- 声明式:使用
onCompletion操作符onCompletion操作符可以接收一个可空的cause参数用于判断流收集是正常完成还是异常导致停止。但它只接收异常不处理异常,它能观察到所有异常,当上游流成功完成(没有取消或失败)的情况下接受一个null异常。onCompletion是最末端操作符,collection是它的上游流,collet没有捕获的异常会被onCompletion接收到。
(1..5).asFlow()
.onCompletion { cause -> cause?.let { println("error:$it") } ?: let { println("Done") } }
.collect {
check(it < 3) { "Collect value" }
println(it)
}
1
2
error:java.lang.IllegalStateException: Collect value
流取消与检测
emit()发出的流可以通过cancel()直接取消,如果要取消asFlow()、flowOf()的流,需要先添加cancellable()操作符进行转化,返回一个可取消的流。
flowOf(1,3,4,5,5)
.cancellable() //检测转换
.collect {
if (it==3) cancel() //取消
println(it) }