Android面试题

kotlin协程上下文和异常处理

2024-05-05  本文已影响0人  AntDream
上下文是什么

CoroutineContext是一组用于定义协程行为的元素,包括以下几部分:

@Test
fun `test coroutine context`() = runBlocking {
    launch(Dispatchers.IO + CoroutineName("test")) {
        println("thread: ${Thread.currentThread().name}")
    }
}
协程上下文的继承

协程的上下文 = 默认值 + 继承的CoroutineContext + 参数

@Test
fun `test coroutine context extend`() = runBlocking {
    val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> 
        println("handle exception: $throwable")
    }
    //scope有了新的CoroutineContext,和runBlocking不一样
    val scope = CoroutineScope(Job() + Dispatchers.Main + coroutineExceptionHandler)
    //job的CoroutineContext继承自scope,但是Job会是新的,每个协程都会有新的Job
    val job = scope.launch(Dispatchers.IO) { 
        //新协程
    }
}

由于传入协程构建器的参数优先级更高,所以job的调度器被覆盖,是Dispatchers.IO而不是父类的Dispatchers.Main

异常

异常的传播

协程构建器有2种传播形式:

异常传播的特性

当一个协程由于一个异常而运行失败时,它会传播这个异常并传递给它的父级。接下来父级会进行下面几步操作:

SupervisorJob和SupervisorScope

异常的捕获

@Test
fun `test exception handler`() = runBlocking {
    val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
        println("handle exception: $throwable")
    }
    val scope = CoroutineScope(Job())
    //能捕获到异常
    val job1 = scope.launch(coroutineExceptionHandler) {
        launch { 
            throw IllegalArgumentException()
        }
    }
    val job2 = scope.launch() {
        //不能捕获到异常
        launch(coroutineExceptionHandler) { 
            throw IllegalArgumentException()
        }
    }
}
Android中全局异常处理
class GlobeCoroutineExceptionHandler : CoroutineExceptionHandler {
    override val key = CoroutineExceptionHandler
    override fun handleException(context: CoroutineContext, exception: Throwable) {
        Log.d("xxx", "unHandle exception: $exception")
    }
}

然后再main目录下,新建resources/META-INF/services目录,然后新建kontlinx.coroutines.CoroutineExceptionHandler文件,内容为:

com.example.kotlincoroutine.GlobeCoroutineExceptionHandler
取消与异常处理
//取消与异常
/*
* 打印顺序为:
* section 3
* section 1
* section 2
* handle exception:ArithmeticException
* 
* */
@Test
fun `test exception handler2`() = runBlocking {
    val handler = CoroutineExceptionHandler { _, throwable ->
        println("handle exception: $throwable")
    }
    val job = GlobalScope.launch(handler) {
        launch {
            try {
                delay(Long.MAX_VALUE)
            }finally {
                withContext(NonCancellable){
                    println("section 1")
                    delay(100)
                    println("section 2")
                }
            }
        }
        launch {
            delay(10)
            println("section 3")
            throw ArithmeticException()
        }
    }
    job.join()
}
异常的聚合
上一篇 下一篇

猜你喜欢

热点阅读