我将翻译三篇介绍协程的 取消 和 异常处理 相关的文章,三篇文章是层层递进的关系。翻译过程中我将尽量忠实于原文。当然,由于水平有限,不能保证完全的翻译正确。如果您发现翻译有错误之处,欢迎在评论里指出。我也将贴出每篇翻译的原文。
- 第一篇:《协程:第一件事》(原文: Coroutines: first things first)
- 第二篇:《协程的取消》(原文:Cancellation in coroutines)
- 第三篇:《协程的异常》(原文:Exceptions in coroutines)
这是第二篇。
文章目录
在开发中,就如在生活中一样,我们都知道避免做多余的事情很重要,因为它会浪费 memory
和 energy
。这一原则也适用于协程。你需要确保自己能控制协程的生命周期,并在不再需要的时候取消它——这就是结构化并发所代表的。请继续阅读,探寻协程取消的来龙去脉。
调用 cancel 方法
当启动多个协程时,追踪或者一个个地取消它们是一件很痛苦的事情。但是,我们可以取消启动协程的整个 scope
,这样我们就能取消在它里面启动的所有子协程。
//假设我们已经定义了一个 scope
val job1 = scope.launch {
... }
val job2 = scope.launch {
... }
scope.cancel()
取消
scope
会取消它的子协程
有时候,你可能只需要取消一个协程,比如说响应用户的输入。调用 job1.cancel
确保只有特定的协程被取消,其它所有的同级别协程不会受影响:
val job1 = scope.launch {
... }
val job2 = scope.launch {
... }
//协程job1会被取消,而其它的不会受影响
job1.cancel()
取消一个子协程不会影响同级别的其它协程
协程通过抛一个特殊的异常(CancellationException
)来处理取消。如果你想为取消的原因提供更多细节,你可以在调用 cancel
方法的时候提供一个 CancellationException
实例,以下是 cancel
方法的完整签名:
fun cancel(cause: CancellationException? = null)
如果你不提供自己的 CancellationException
实例,一个默认的CancellationException
实例将被创建,如下:
public override fun cancel(cause: CancellationException?) {
cancelInternal(cause ?: defaultCancellationException())
}
因为CancellationException
被抛出,你能通过该机制来处理协程的取消。更多关于如何取消的内容请阅读后面的章节 处理取消的副作用。
在协程底层,子 job
通过异常来通知父节点它的取消。父节点使用取消的 cause
来判断是否处理这个异常。如果子任务是因为 CancellationException
被取消,