• 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的异常是捕获不到的。内部是不行的外部可以。

  • 相关阅读:
    一个基于.NET Core构建的简单、跨平台、模块化的商城系统
    【数据库原理及应用】——关系操作、关系完整性、关系代数(万字大总结)
    java面向对象的三大特征【继承、封装、多态】
    单源最短路径 dijkstra
    Programming Differential Privacy第十一章The Sparse Vector Technique稀疏向量技术
    jupyter notebook中使用不同的anaconda环境及常用conda命令
    qiankun - 微前端应用搭建
    时间轴_3D打印
    Qt:信号与槽机制
    vue.js毕业设计,基于vue.js前后端分离在线小说电子书阅读小程序系统设计与实现
  • 原文地址:https://blog.csdn.net/mp624183768/article/details/126450421