CoroutineExceptionHandler使用的踩坑日志

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的问题,再到最后,原来,源码里早有答案。。。。还是要多多看看源码注释啊。

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin协程是一种轻量级的线程处理机制,它可以在不创建新线程的情况下实现异步操作。Kotlin协程的优势在于它提供了一种结构化并发的方式,使得异步代码更加易于编写和维护。下面是深入理解Kotlin协程的一些方法和步骤: 1. 协程的基本概念:协程是一种轻量级的线程处理机制,它可以在不创建新线程的情况下实现异步操作。协程的本质是一种协作式的多任务处理机制,它可以在同一个线程中切换执行不同的任务,从而实现异步操作。 2. 协程使用方法:在Kotlin中,协程使用方法非常简单。首先需要导入kotlinx.coroutines库,然后使用launch函数创建一个协程。在协程中可以使用挂起函数来实现异步操作,例如delay函数可以让协程暂停一段时间。 3. 协程的挂起函数:协程的挂起函数是一种特殊的函数,它可以让协程暂停执行,等待某个条件满足后再继续执行。在Kotlin中,常用的挂起函数包括delay函数、withContext函数和async函数等。 4. 协程的上下文:协程的上下文是一种特殊的对象,它包含了协程的执行环境和状态信息。在Kotlin中,协程的上下文可以通过CoroutineContext对象来表示,它包含了协程的调度器、异常处理器和其他一些属性。 5. 协程异常处理:协程异常处理是一种特殊的机制,它可以让协程在发生异常时自动恢复或者终止执行。在Kotlin中,协程异常处理可以通过try-catch语句或者CoroutineExceptionHandler对象来实现。 6. 协程的取消:协程的取消是一种特殊的机制,它可以让协程在不需要继续执行时自动终止。在Kotlin中,协程的取消可以通过cancel函数或者协程作用域来实现。 下面是一个使用Kotlin协程实现异步操作的例子: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { val job = launch { delay(1000L) println("World!") } println("Hello,") job.join() } ``` 输出结果为: ``` Hello, World! ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值