一、异常处理
1.收集(collect)的时候(下游)出现的异常
- 使用
try-catch
块来捕获在收集流时可能抛出的异常(命令式)。
fun simpleFlow() = flow{
for (i in 1..3){
println("Emitting $i")
emit(i)
}
}
@Test
fun testFlow1() = runBlocking<Unit> {
try {
simpleFlow().collect {value ->
println(value)
check(value <= 1){"Collected $value"}//不符合会抛出异常
}
} catch (e : Throwable){
println("Caught $e")
}
}
可见3并没有输出,因为在check(value <= 1){"Collected $value"}这一步发现了异常,用catch (e : Throwable)来进行捕获
2.在Flow构建的时候(上游)出现了异常
使用 catch
块来捕获在产生流时可能抛出的异常(声明式)。
@Test
fun testFlow2() = runBlocking<Unit> {
flow {
emit(1)
throw ArithmeticException("Div 0")
}.catch { e: Throwable -> println("Caught $e") }
.flowOn(Dispatchers.IO)
.collect{println(it)}
}
肯定有同学在疑惑为什么这样子做,使用catch和try-catch具体有什么区别,下面我来简单解释一下:
流的创建阶段:在流的创建阶段,使用 catch
操作符可以确保在流内部发生异常时进行处理。这样可以更好地控制流的行为,并在异常发生时采取适当的措施,例如日志记录、默认值提供等。就是说上流这种设计模式只是想捕获到异常然后更好的处理流上层的问题,比如 这段代码:捕获到了异常仍可以更新数据
流的收集阶段:在收集流的时候,使用 try-catch
块可以更灵活地处理异常。由于收集阶段是在调用流的地方,可能有不同的上下文和需求,因此在这里使用 try-catch
可以根据具体情况采取不同的异常处理策略。
假如你使用try-catch的话,不仅臃肿,而且也没必要,不适合上层流构建的设计模式
更新的emit(10)直接报错了
二、Flow完成处理
finally (命令式):您可以在流的收集器中使用 finally
块来执行无论流是否正常完成或异常完成都需要执行的清理操作。finally
块中的代码将在流完成后执行,无论是正常完成还是异常完成。
onCompletion (声明式):onCompletion
操作符用于指定当流完成时要执行的操作。与 finally
块不同,onCompletion
操作符允许您访问到流完成时的异常信息(如果有的话),并且可以选择性地处理异常信息,简单来讲就是能抛出异常信息(上游下游都可以抛出),但不能捕获,要捕获的话需要使用catch(上游)或者try-catch(下游)->又和之前对应了