Kotlin Coroutines Exception

Kotlin Coroutines Exception

官方文档:https://www.kotlincn.net/docs/reference/coroutines/exception-handling.html

kotlin coroutines的exception有几种容易混淆的处理情形,在这里列举一下:

withContext

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

Async

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!

coroutineScope + Async

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

supervisorScope + Async

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

协程内部使用 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

你可能感兴趣的:(android)