美文网首页Android 知识Kotlin 知识
Kotlin(二十)异步流-操作符<4> 异常处理

Kotlin(二十)异步流-操作符<4> 异常处理

作者: zcwfeng | 来源:发表于2021-08-04 19:28 被阅读0次
  1. 流异常

当运算符中的发射器或代码抛出异常时,流收集可以带有异常的完成。 有几种处理异常的方法。

收集器 try 与 catch

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i) // 发射下一个值
    }
}

fun main() = runBlocking<Unit> {
    try {
        simple().collect { value ->         
            println(value)
            check(value <= 1) { "Collected $value" }
        }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}            


Emitting 1
1
Emitting 2
2
Caught java.lang.IllegalStateException: Collected 2

这段代码成功的在末端操作符 [collect]中捕获了异常,并且, 如我们所见,在这之后不再发出任何值

一切都已捕获

fun simple(): Flow<String> = 
    flow {
        for (i in 1..3) {
            println("Emitting $i")
            emit(i) // 发射下一个值
        }
    }
    .map { value ->
        check(value <= 1) { "Crashed on $value" }                 
        "string $value"
    }

fun main() = runBlocking<Unit> {
    try {
        simple().collect { value -> println(value) }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}  


Emitting 1
string 1
Emitting 2
Caught java.lang.IllegalStateException: Crashed on 2

仍然会捕获该异常并停止收集:

前面的示例实际上捕获了在发射器或任何过渡或末端操作符中发生的任何异常。 例如,让我们修改代码以便将发出的值[映射]为字符串, 但是相应的代码会产生一个异常

异常透明性

但是,发射器的代码如何封装其异常处理行为?

流必须对异常透明,即在 flow { ... } 构建器内部的 try/catch 块中[发射]值是违反异常透明性的。这样可以保证收集器抛出的一个异常能被像先前示例中那样的 try/catch 块捕获。

发射器可以使用 [catch](操作符来保留此异常的透明性并允许封装它的异常处理。catch 操作符的代码块可以分析异常并根据捕获到的异常以不同的方式对其做出反应

  • 可以使用 throw 重新抛出异常。
  • 可以使用 [catch] 代码块中的 [emit]( 将异常转换为值发射出去。
  • 可以将异常忽略,或用日志打印,或使用一些其他代码处理它。
simple()
    .catch { e -> emit("Caught $e") } // 发射一个异常
    .collect { value -> println(value) }

Emitting 1
string 1
Emitting 2
Caught java.lang.IllegalStateException: Crashed on 2

透明捕获

过渡操作符遵循异常透明性,仅捕获上游异常(catch 操作符上游的异常,但是它下面的不是)。 如果 collect { ... } 块(位于 catch 之下)抛出一个异常,那么异常会逃逸:

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i)
    }
}

fun main() = runBlocking<Unit> {
    simple()
        .catch { e -> println("Caught $e") } // 不会捕获下游异常
        .collect { value ->
            check(value <= 1) { "Collected $value" }                 
            println(value) 
        }
}            

Emitting 1
1
Emitting 2
Exception in thread "main" java.lang.IllegalStateException: Collected 2
 at FileKt$main$1$invokeSuspend$$inlined$collect$1.emit (Collect.kt:135) 
 at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$$inlined$collect$1.emit (Collect.kt:136) 
 at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke (SafeCollector.kt:15)


尽管有 catch 操作符,但不会打印“Caught …”消息:

声明式捕获

我们可以将 [catch] 操作符的声明性与处理所有异常的期望相结合,将 [collect]操作符的代码块移动到 [onEach]中,并将其放到 catch 操作符之前。收集该流必须由调用无参的 collect() 来触发:

simple()
    .onEach { value ->
        check(value <= 1) { "Collected $value" }                 
        println(value) 
    }
    .catch { e -> println("Caught $e") }
    .collect()

Emitting 1
1
Emitting 2
Caught java.lang.IllegalStateException: Collected 2

现在我们可以看到已经打印了“Caught …”消息,并且我们可以在没有显式使用 try/catch 块的情况下捕获所有异常

相关文章

  • Kotlin(二十)异步流-操作符<4> 异常处理

    流异常 当运算符中的发射器或代码抛出异常时,流收集可以带有异常的完成。 有几种处理异常的方法。 收集器 try 与...

  • Kotlin(二十)异步流-操作符<2>

    流上下文 流的收集总是在调用协程的上下文中发生。例如,如果有一个流 simple,然后以下代码在它的编写者指定的上...

  • Kotlin(二十)异步流-操作符<1>

    过渡流操作符 我们可以参考RxJava 思考 可以使用操作符转换流,就像使用集合与序列一样。 过渡操作符应用于上游...

  • Kotlin(二十)异步流-操作符<3>

    处理最新值 当发射器和收集器都很慢的时候,合并是加快处理速度的一种方式。它通过删除发射值来实现。 另一种方式是取消...

  • 同步或异步异常处理

    同步或异步异常处理 同步读取异常处理 异步读取文件异常处理

  • Kotlin(二十)异步流-操作符<5> 流完成

    流完成 当流收集完成时(普通情况或异常情况),它可能需要执行一个动作。 你可能已经注意到,它可以通过两种方式完成:...

  • Kotlin(二十)异步流 开始

    异步流 挂起函数可以异步的返回单个值,但是该如何异步返回多个计算好的值呢?这正是 Kotlin 流(Flow)的用...

  • 破解 Kotlin 协程(4) - 异常处理篇

    关键词:Kotlin 协程 异常处理 异步代码的异常处理通常都比较让人头疼,而协程则再一次展现了它的威力。 1. ...

  • Kotlin Flow 介绍

    1.Kotlin Flow 介绍 翻译下就是:按顺序发出值并正常完成或异常完成的Cold异步数据流。 Hot Ob...

  • Kotlin异步流

    一、表示多个值 Kotlin 中可以使用集合来表示多个值 1.序列 2.挂起函数 计算过程阻塞运行该代码的主线程。...

网友评论

    本文标题:Kotlin(二十)异步流-操作符<4> 异常处理

    本文链接:https://www.haomeiwen.com/subject/xwauvltx.html