kotlin: 异常捕捉不到的情况
一,CoroutineExceptionHandler捕获异常的条件
CoroutineExceptionHandler 捕获异常需要两个条件:
- 这个异常是自动传播的。
- CoroutineExceptionHandler 位于 CoroutineScope 的 CoroutineContext 中,
或 supervisorScope 的直接子协程中,或其他根协程中。
这样的设计是合理的,
因为 CoroutineScope 的子协程不应该捕获异常,CoroutineScope 的设定就是子协程的异常交由父类处理,
所以应该在 CoroutineScope 创建的根协程中捕获此异常。
而 supervisorScope 的设定是子协程的异常自己处理,所以 supervisorScope 的子协程可以自己捕获异常。
二,例子:捕捉不到异常
原因: handler 放在了 scope 子协程的子协程中,
这时异常会往父协程抛出,不会被自己捕获
代码:
//处理按钮点击事件
binding.button1.setOnClickListener {
runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("捕捉到了异常: $e")
}
val scope = CoroutineScope(Job())
val job = scope.launch {
launch(handler) {
println("将要抛出异常")
throw Exception("发生了异常")
}
}
job.join()
}
}
运行结果:

三,例子,把handler放到父协程中,使可以捕捉到异常
代码:
//处理按钮点击事件
binding.button2.setOnClickListener {
runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("捕捉到了异常: $e")
}
val scope = CoroutineScope(Job())
val job = scope.launch(handler) {
launch {
println("将要抛出异常")
throw Exception("发生了异常")
}
}
job.join()
}
}
参数也可以放到scope中,如下
//处理按钮点击事件
binding.button2.setOnClickListener {
runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("捕捉到了异常: $e")
}
val scope = CoroutineScope(Job()+handler)
val job = scope.launch {
launch {
println("将要抛出异常")
throw Exception("发生了异常")
}
}
job.join()
}
}
运行结果:

浙公网安备 33010602011771号