返回

Kotlin协程官方教程(7):异常处理

Android

引言

本篇教程深入探讨Kotlin协程在异常处理和取消异常方面的机制。之前我们了解到,取消协程会导致挂起点抛出CancellationException,但协程机制会忽略此异常。然而,如果在取消过程中抛出异常,或协程有多个子协程抛出异常,会发生什么情况呢?

协程构建器类型

协程构建器有两种类型,处理异常的方式不同:

1. 自动传播异常

  • 使用launch函数创建的协程。
  • 如果在协程中抛出异常,则会自动传播到父协程或调用者。
  • 父协程或调用者可以处理异常。

2. 取消异常

  • 使用async函数创建的协程。
  • 如果协程因取消而被终止,则CancellationException会自动传播到父协程或调用者。
  • 如果协程在取消期间抛出其他异常,则该异常将被忽略。

异常处理

1. try-catch块

在协程中使用try-catch块可以捕捉异常,就像在常规代码中一样。

try {
    // 协程代码
} catch (e: Exception) {
    // 异常处理
}

2. superviseJob

superviseJob函数可以创建一个作业,即使子协程抛出异常,它也不会取消。这是隔离异常的便捷方法。

val supervisorJob = SupervisorJob()
val childJob = launch(supervisorJob) {
    // 协程代码
}

取消异常

1. Cooperative Cancellation

CancellationException可以在挂起点抛出,以协作方式取消协程。

coroutineScope.launch {
    try {
        // 协程代码
    } catch (e: CancellationException) {
        // 取消处理
    }
}

2. Non-Cooperative Cancellation

如果在非挂起点抛出异常,则协程将被非协作地取消。这会导致CancellationException被忽略。

最佳实践

  • 优先使用自动传播异常的构建器,因为它更直观,也更易于调试。
  • 在取消期间需要隔离异常时,可以使用superviseJob
  • 使用try-catch块来处理协程中的异常。
  • 抛出CancellationException来协作取消协程。
  • 小心非协作取消,因为它会忽略异常。

案例研究:弹性协程

以下示例演示了如何使用协程构建器类型和异常处理来创建弹性协程:

// 父协程使用自动传播异常构建器
coroutineScope.launch {
    // 创建子协程并分配给作业
    val childJob = launch {
        try {
            // 执行子协程代码
        } catch (e: Exception) {
            // 捕获子协程异常
            // 继续执行父协程
        }
    }
    
    // 等待子协程完成
    childJob.join()
}

结论

Kotlin协程提供了强大的异常处理机制,允许开发人员灵活地处理协程中的异常情况。通过理解协程构建器类型和最佳实践,您可以构建弹性、健壮的协程应用程序。