协程的异常处理3:协程的异常

我将翻译三篇介绍协程的 取消异常处理 相关的文章,三篇文章是层层递进的关系。翻译过程中我将尽量忠实于原文。当然,由于水平有限,不能保证完全的翻译正确。如果您发现翻译有错误之处,欢迎在评论里指出。我也将贴出每篇翻译的原文。

这是第三篇。



我们开发者通常花费大量时间打磨应用的正常使用场景。然而,当应用发生意外时,合适的用户体验也同样重要。一方面,对用户来说应用发生崩溃是糟糕的体验;另一方面,当操作执行失败时,给用户提示适当的信息是必不可少的。

合理的异常处理将对用户如何看待你的应用产生很大的影响。在这篇文章中,我们将解释协程中的异常如何传播,以及如何通过多种方式控制它们。



协程突然失败了!怎么办?😱

当一个协程因为异常失败时,它会把异常传播给它的父节点!然后,这个父节点会 1) 取消其余的子协程,2) 取消自己, 3) 把异常传播给自己的父节点。

异常将被传播到层次结构的根节点,所有由这个根节点 CoroutineScope发起的协程都将被取消。

在这里插入图片描述

协程中发生的异常将通过协程的层次结构向上传播

有些情况下这种异常传播是合理的,然而也有些情况不需要这样。试想,有一个与UI相关的 CoroutineScope,用来处理用户交互。如果其中一个子协程抛了异常,那么这个UI scope将被取消,并且整个UI模块将变得无法响应,因为一个被取消的 scope不能再启动协程。

如果你不想要这样的行为该怎么办?作为替代,你可以在创建协程的 CoroutineScopeCoroutineContext中用一个不同的 Job实现,名叫 SuervisorJob


拯救者 SupervisorJob

使用 SupervisorJob,子协程的失败不会影响其余子协程。一个 SupervisorJob不会取消它自己或它的子协程。而且,SupervisorJob也不会传播异常,它会让子协程自己处理异常。

你可以这样创建一个 CoroutineScope:

val uiScope = CoroutineScope(SupervisorJob())

当一个协程失败时,它不会传播取消,如下图所示:

在这里插入图片描述

(一个 SupervisorJob不会因为异常取消自身或其余的子协程)

如果异常没有被处理,并且 CoroutineContext没有 CoroutineExceptionHandler,异常将到达默认线程的 ExceptionHandler。在JVM中,异常将被记录到控制台;在Android中,不管异常发生在哪个线程,都将导致app崩溃。

💥未捕获的异常总会被抛出,不管你使用哪种 Job

同样的行为也适用于 scope构建器 coroutineScopesupervisorScope。这两种构建器将创建一个子 scope(使用 JobSupervisorJob),你可以用它们来组织协程(比如说你想做并行计算,或者你希望它们相互影响or相互不影响)。

提醒SupervisorJob只有在其作为 scope的一部分时才起作用,要么使用 supervisorScope创建,要么使用 CoroutineScope(SuperVisorJob())创建。


Job 还是 SupervisorJob ?🤔

什么时候该使用 Job或者 SupervisorJob?当你不希望失败导致父节点或同级节点被取消时&#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值