Android 协程 异常捕获 异常的传播特性
Posted 安果移不动
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 协程 异常捕获 异常的传播特性相关的知识,希望对你有一定的参考价值。
@Test
fun `test exception propagation`() = runBlocking<Unit>
val job = GlobalScope.launch
try
throw IndexOutOfBoundsException()
catch (e: Exception)
println("Caught: $e")
job.join()
val deferred = GlobalScope.async
throw ArithmeticException()
try
deferred.await()
catch (e: Exception)
println("Caught: $e")
delay(1000)
launch的异常是再方法体里面 无论是否执行
job.join()
都会报错/
而async的异常则是需要在await的时候才会抛出来
不执行则不会抛出来异常
@Test
fun `test exception propagation2`() = runBlocking<Unit>
val scope = CoroutineScope(Job())
val job = scope.launch
//非根协程的异常 launch就会立即抛出异常
async
throw IllegalArgumentException()
job.join()
异常的传播特性
当一个协程由于一个异常而运行失败时,它会传播这个异常并传递给他的父级。接下来,
父级会
1、取消它自己的子级
2、取消它自己
3、将异常传播并传递给它的父级
很对情况下这不是我们想要的 可以是用
SupervisorJob
@Test
fun `test SupervisorJob`() = runBlocking<Unit>
val supervisor = CoroutineScope(SupervisorJob())
val job1 = supervisor.launch
delay(1000)
println("child 1")
throw IllegalArgumentException()
val job2 = supervisor.launch
try
delay(Long.MAX_VALUE)
finally
println("child 2 finished")
joinAll(job1, job2)
这是一个进行中的状态。程序依然在执行
这说明他不会影响它的child协程的执行
换成Job后
val supervisor = CoroutineScope(Job())
程序会执行结束。 和我们上面说的生命周期一样。
也可以是用
supervisorScope 效果是和SupervisorJob 一样的
@Test
fun `test SupervisorScope`() = runBlocking<Unit>
supervisorScope
launch
delay(1000)
println("child 1")
throw IllegalArgumentException()
launch
try
delay(Long.MAX_VALUE)
finally
println("child 2 finished")
但是如果父协程的抛出了异常。子协程也会跟着退出
@Test
fun `test SupervisorScope2`() = runBlocking<Unit>
supervisorScope
try
val child = launch
println("The child is sleeping")
delay(Long.MAX_VALUE)
finally
println("The child is over")
yield()
println("Throwing an exception from the scope")
throw AssertionError()
捕获的异常的时机与位置
@Test
fun `test CoroutineExceptionHandler`() = runBlocking<Unit>
val coroutineExceptionHandler = CoroutineExceptionHandler _, exception ->
println("Caught $exception")
val job1 = GlobalScope.launch(coroutineExceptionHandler)
throw AssertionError()
val job2 = GlobalScope.async(coroutineExceptionHandler)
throw ArithmeticException()
job1.join()
job2.await()
@Test
fun `test CoroutineExceptionHandler2`() = runBlocking<Unit>
val coroutineExceptionHandler = CoroutineExceptionHandler _, exception ->
println("Caught $exception")
val scope = CoroutineScope(Job())
val job = scope.launch(coroutineExceptionHandler)
launch
throw IllegalArgumentException()
job.join()
@Test
fun `test CoroutineExceptionHandler3`() = runBlocking<Unit>
val coroutineExceptionHandler = CoroutineExceptionHandler _, exception ->
println("Caught $exception")
val scope = CoroutineScope(Job())
val job = scope.launch()
launch(coroutineExceptionHandler)
throw IllegalArgumentException()
job.join()
test CoroutineExceptionHandler2的异常是可以捕获到的
test CoroutineExceptionHandler3的异常是捕获不到的。内部是不行的外部可以。
以上是关于Android 协程 异常捕获 异常的传播特性的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程协程异常处理 ① ( 根协程异常处理 | 自动传播异常 | 在协程体捕获异常 | 向用户暴露异常 | 在 await 处捕获异常 | 非根协程异常处理 | 异常传播特性 )
Kotlin 协程协程异常处理 ② ( SupervisorJob 协程 | supervisorScope 协程作用域构建器函数 )
Kotlin 协程协程异常处理 ② ( SupervisorJob 协程 | supervisorScope 协程作用域构建器函数 )
Kotlin 协程协程异常处理 ⑤ ( 异常传播的特殊情况 | 取消子协程示例 | 子协程抛出异常后父协程处理异常时机示例 | 异常聚合 | 多个子协程抛出的异常会聚合到第一个异常中 )
Kotlin 协程协程异常处理 ⑤ ( 异常传播的特殊情况 | 取消子协程示例 | 子协程抛出异常后父协程处理异常时机示例 | 异常聚合 | 多个子协程抛出的异常会聚合到第一个异常中 )
Kotlin 协程协程异常处理 ④ ( Android 协程中出现异常导致应用崩溃 | Android 协程中使用协程异常处理器捕获异常 | Android 全局异常处理器 )