• Android 协程 异常捕获 异常的传播特性


    1. @Test
    2. fun `test exception propagation`() = runBlocking<Unit> {
    3. val job = GlobalScope.launch {
    4. try {
    5. throw IndexOutOfBoundsException()
    6. } catch (e: Exception) {
    7. println("Caught: ${e}}")
    8. }
    9. }
    10. job.join()
    11. val deferred = GlobalScope.async {
    12. throw ArithmeticException()
    13. }
    14. try {
    15. deferred.await()
    16. } catch (e: Exception) {
    17. println("Caught: ${e}}")
    18. }
    19. delay(1000)
    20. }

    launch的异常是再方法体里面 无论是否执行 

     job.join()

    都会报错/

    而async的异常则是需要在await的时候才会抛出来

    不执行则不会抛出来异常

    1. @Test
    2. fun `test exception propagation2`() = runBlocking<Unit> {
    3. val scope = CoroutineScope(Job())
    4. val job = scope.launch {
    5. //非根协程的异常 launch就会立即抛出异常
    6. async {
    7. throw IllegalArgumentException()
    8. }
    9. }
    10. job.join()
    11. }

     异常的传播特性

    当一个协程由于一个异常而运行失败时,它会传播这个异常并传递给他的父级。接下来,

    父级会

    1、取消它自己的子级

    2、取消它自己

    3、将异常传播并传递给它的父级

    很对情况下这不是我们想要的 可以是用

    SupervisorJob

    1. @Test
    2. fun `test SupervisorJob`() = runBlocking<Unit> {
    3. val supervisor = CoroutineScope(SupervisorJob())
    4. val job1 = supervisor.launch {
    5. delay(1000)
    6. println("child 1")
    7. throw IllegalArgumentException()
    8. }
    9. val job2 = supervisor.launch {
    10. try {
    11. delay(Long.MAX_VALUE)
    12. } finally {
    13. println("child 2 finished")
    14. }
    15. }
    16. joinAll(job1, job2)
    17. }

     这是一个进行中的状态。程序依然在执行

    这说明他不会影响它的child协程的执行

    换成Job后

      val supervisor = CoroutineScope(Job())

     程序会执行结束。 和我们上面说的生命周期一样。

    也可以是用

    supervisorScope 效果是和SupervisorJob 一样的

    1. @Test
    2. fun `test SupervisorScope`() = runBlocking<Unit> {
    3. supervisorScope {
    4. launch {
    5. delay(1000)
    6. println("child 1")
    7. throw IllegalArgumentException()
    8. }
    9. launch {
    10. try {
    11. delay(Long.MAX_VALUE)
    12. } finally {
    13. println("child 2 finished")
    14. }
    15. }
    16. }
    17. }

    但是如果父协程的抛出了异常。子协程也会跟着退出

    1. @Test
    2. fun `test SupervisorScope2`() = runBlocking<Unit> {
    3. supervisorScope {
    4. try {
    5. val child = launch {
    6. println("The child is sleeping")
    7. delay(Long.MAX_VALUE)
    8. }
    9. } finally {
    10. println("The child is over")
    11. }
    12. yield()
    13. println("Throwing an exception from the scope")
    14. throw AssertionError()
    15. }
    16. }

     捕获的异常的时机与位置

     

    1. @Test
    2. fun `test CoroutineExceptionHandler`() = runBlocking<Unit> {
    3. val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
    4. println("Caught $exception")
    5. }
    6. val job1 = GlobalScope.launch(coroutineExceptionHandler) {
    7. throw AssertionError()
    8. }
    9. val job2 = GlobalScope.async(coroutineExceptionHandler) {
    10. throw ArithmeticException()
    11. }
    12. job1.join()
    13. job2.await()
    14. }

     

    1. @Test
    2. fun `test CoroutineExceptionHandler2`() = runBlocking<Unit> {
    3. val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
    4. println("Caught $exception")
    5. }
    6. val scope = CoroutineScope(Job())
    7. val job = scope.launch(coroutineExceptionHandler) {
    8. launch {
    9. throw IllegalArgumentException()
    10. }
    11. }
    12. job.join()
    13. }
    14. @Test
    15. fun `test CoroutineExceptionHandler3`() = runBlocking<Unit> {
    16. val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
    17. println("Caught $exception")
    18. }
    19. val scope = CoroutineScope(Job())
    20. val job = scope.launch() {
    21. launch(coroutineExceptionHandler) {
    22. throw IllegalArgumentException()
    23. }
    24. }
    25. job.join()
    26. }

    test CoroutineExceptionHandler2的异常是可以捕获到的

    test CoroutineExceptionHandler3的异常是捕获不到的。内部是不行的外部可以。

  • 相关阅读:
    (Note)同比和环比
    Ubuntu使用GParted增加swap分区后无法休眠解决办法
    C语言基础知识点(九)数据类型溢出
    UML建模
    一步一图带你深入理解 Linux 虚拟内存管理
    Hive 中的各种常用set设置
    私有云:架构图
    ✔ ★【备战实习(面经+项目+算法)】 10.25学习(算法刷题:5道)
    高效技巧揭秘:Java轻松批量插入或删除Excel行列操作
    【Kubernetes 系列】一文带你吃透 K8S 应用pod结点
  • 原文地址:https://blog.csdn.net/mp624183768/article/details/126450421