CoroutineScope作用域
下面这段使用coroutineScope作用域,在第7行launch中抛出了异常,即使在该launch的父协程,也就是coroutineScope的根协程设置了捕获(即第三行设置了捕获),也并不会执行该捕获。异常还是会向上传输给根作用域lifecycleScope中的根launch(即第一行的launch)。所以这里需要在第一行的launch那里,即在coroutineScope中,只有在根协程设置CoroutineExceptionHandler才有效。
lifecycleScope.launch {
coroutineScope {
launch(CoroutineExceptionHandler { coroutineContext, throwable ->
Log("捕获到了异常~")
}){
Log(1)
launch {
Log(2)
throw ArithmeticException("抛出异常了~")
}
}
}
launch {
Log("路人甲")
delay(1000)
Log("来了个路人乙")
}
}
执行结果:
supervisorScope作用域
上面相同的代码,只是把coroutineScope换成了supervisorScope的话,输出为:
发现异常可以在sueprvisorScope的根launch捕获了,并且不会向上继续给lifecycleScope了。
如果supervisorScope的根launch并未设置捕获,异常还是会继续向上传输的。如下图:
lifecycleScope.launch(CoroutineExceptionHandler { coroutineContext, throwable ->
Log("根协程捕获到了异常")
}) {
supervisorScope {
launch {
Log(1)
launch {
Log(2)
throw ArithmeticException("抛出异常了~")
}
}
}
launch {
Log("路人甲")
delay(1000)
Log("来了个路人乙")
}
}
输出结果:
小结
coroutinieScope作用域中的子协程出了异常,即使在coroutineScope的作用域下的根launch设置了CoroutineExceptionHandler也是无效果的,异常还是会继续向上传递给父作用域的根协程,最终导致整个作用域异常取消。
如果是使用了supervisorScope的话,异常可以在supervisorScope的根launch设置CoroutineExceptionHandler捕获,并且不会继续向上传递异常。
番外1:try....catch牛逼
下面这段代码,不论是coroutiineScope还是supervisorScope,使用try..catch都能捕获异常!而且异常不会继续向上传输。
lifecycleScope.launch(CoroutineExceptionHandler { coroutineContext, throwable ->
Log("根协程捕获到了异常")
}) {
coroutineScope {
launch {
Log(1)
launch {
try {
Log(2)
throw ArithmeticException("抛出异常了~")
} catch (e: Exception) {
Log("自己捕获")
}
}
}
}
launch {
Log("路人甲")
delay(1000)
Log("来了个路人乙")
}
}
输出结果:
番外2:CoroutineExceptionHandler的使用注意
简单来说,我的理解为:CoroutineExceptionHandler默认只能在根协程设置,子协程设置是无效的。
补充:
最早是发现的supervisorScope作用域中,根launch设置coroutineExceptonHandler竟然可以捕获到异常,最后慢慢扩展发现了coroutineExceptionHandler的问题,再到最后,原来,源码里早有答案。。。。还是要多多看看源码注释啊。