当前位置:网站首页>Kotlin协程 - 异常处理

Kotlin协程 - 异常处理

2022-08-09 07:25:00 懒到死的程序员

异常的传播 

Job的异常传播是双向的,如果异常在局部没有捕获处理便不会重新抛出而是不停地向上传播,由于结构化并发的特性,层次结构中的所有协程都会都会被取消:

  1. 发生异常先取消自己的所有子协程,接着取消自己,然后将异常传递给父协程;
  2. 父协程先取消自己的所有子协程,接着取消自己,然后再向上传递一直到根协程。
launchasync
作为根协程时异常直接抛出异常通过最终消费即调用await()才抛出
作为子协程时异常直接抛出 

打断传播

当不希望异常向上传播或影响兄弟协程时使用(向下传播依然存在)。

SupervisorScope()supervisorJob
子协程发生异常会将该作用域内所有协程取消,但不会影响外部。

子协程发生异常不会影响到父协程和兄弟协程。

supervisorScope{
    launch{
        println("子协程1")
        throw Exception()
    }
    launch{
        println("子协程2")
    }
}

suspend fun main() = runBlocking{
    launch(supervisorJob()){
        println("子协程1")
        throw Exception()
    }
    launch{
        println("子协程2")
    }
}

异常的捕获

try-catch

局部捕获

CoroutineExceptionHandler

全局捕获

只能捕获具体代码。捕获协程构建器是无效的,因为结构化并发的原因,无法阻止异常导致的连锁取消。在根协程处捕获作用域内那些未处理的异常,由于达到了顶部,此时内部的连锁取消已完成。

CoroutineExceptionHandler

CoroutineExceptionHandler使用条件:

  • 要么存在于协程作用域的上下文中
  • 要么存在于根协程的直接子协程中

异常会一直向上传播到根协程,根协程如果不作响应(SupervisorScope()或 supervisorJob),则直接子协程会在 coroutineContext 中寻找 CoroutineExceptionHandler 处理,否则走 UncaughtExceptionHandler,所以其它子协程中的 CoroutineExceptionHandler 不会起作用。

以下条件满足时异常会被捕获:

  • 时机:会自动抛出异常的协程所抛出的异常(使用launch而不是async);
  • 位置:在协程作用域的上下文中或根协程的直接子协程中。

Android全局异常捕获

可以获取到所有协程未处理的异常,但不能对异常进行捕获,也不能阻止程序崩溃。创建app/src/main/resources/META-INF/services目录,并创建名为 kotlinx.coroutines.CoroutineExceptionHandler的文件,文件的内容填入创建的全局异常处理器的类名。 

原网站

版权声明
本文为[懒到死的程序员]所创,转载请带上原文链接,感谢
https://blog.csdn.net/HugMua/article/details/126215270