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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值