官方文档:https://www.kotlincn.net/docs/reference/coroutines/exception-handling.html
kotlin coroutines的exception有几种容易混淆的处理情形,在这里列举一下:
GlobalScope.launch(Dispatchers.Main) {
try {
withContext(Dispatchers.IO) {
Log.d("coroutine exception", "start to throw")
throw java.lang.Exception("hahaha")
}
} catch (e : java.lang.Exception){
Log.d("coroutine exception", "outside "+e.message)
}
}
运行结果:
coroutine exception: start throw
coroutine exception: outside hahaha
GlobalScope.launch(Dispatchers.Main) {
try {
async {
Log.d("coroutine exception", "start throw")
throw java.lang.Exception("hahaha")
}.await()
} catch (e : java.lang.Exception){
Log.d("coroutine exception", "outside "+e.message)
}
}
运行结果:
coroutine exception: start throw
coroutine exception: outside hahaha
App Crash!
GlobalScope.launch(Dispatchers.Main) {
try {
coroutineScope {
try {
async {
Log.d("coroutine exception", "start throw")
throw java.lang.Exception("hahaha")
}.await()
} catch (e : java.lang.Exception){
Log.d("coroutine exception", "inside "+e.message)
}
}
} catch (e: Exception) {
Log.d("coroutine exception", "outside " + e.message)
}
}
运行结果:
coroutine exception: start throw
coroutine exception: inside hahaha
coroutine exception: outside hahaha
GlobalScope.launch(Dispatchers.Main) {
try {
supervisorScope {
try {
async {
Log.d("coroutine exception", "start throw")
throw java.lang.Exception("hahaha")
}.await()
} catch (e : java.lang.Exception){
Log.d("coroutine exception", "inside "+e.message)
}
}
} catch (e: Exception) {
Log.d("coroutine exception", e.message)
}
}
运行结果:
coroutine exception: start throw
coroutine exception: inside hahaha
协程内部使用 CancellationException 来进行取消,这个异常会被所有的处理者忽略,所以那些可以被 catch 代码块捕获的异常仅仅应该被用来作为额外调试信息的资源。 当一个协程在没有任何理由的情况下使用 Job.cancel 取消的时候,它会被终止,但是它不会取消它的父协程。 无理由取消是父协程取消其子协程而非取消其自身的机制。
val job = launch {
val child = launch {
try {
delay(Long.MAX_VALUE)
} finally {
println("Child is cancelled")
}
}
yield()
println("Cancelling child")
child.cancel()
child.join()
yield()
println("Parent is not cancelled")
}
job.join()
运行结果:
Cancelling child
Child is cancelled
Parent is not cancelled