Kotlin 协程的核心概念
1. CoroutineScope
CoroutineScope 是协程生命周期的管理者,它可以追踪你通过 launch 和 async 启动的协程(这两个函数是 CoroutineScope 的扩展函数)。你可以通过调用 scope.cancel() 来取消当前的协程。在 Android 中,KTX 库为你提供了可以感知生命周期的 CoroutineScope,如 viewModelScope 和 lifecycleScope,它们会在适当的时候自动取消协程。
创建一个 CoroutineScope 时,需要一个 CoroutineContext 作为其构造函数的参数:
// Job 和 Dispatcher 组合成 CoroutineContext
val scope = CoroutineScope(Job() + Dispatchers.Main)
val job = scope.launch {
// 启动新的协程
}
在这个例子中,CoroutineScope 包含了 Job() 和 Dispatchers.Main,确保协程在主线程中执行并且具有生命周期管理。
2. Job
Job 是协程的句柄。每个通过 launch 或 async 启动的协程都会返回一个 Job 实例,它是协程的唯一标识符,并且可以用来管理协程的生命周期。通过 Job,你可以控制协程的取消、监控其完成状态等。
例如:
val job = scope.launch {
// 启动的协程
}
每个协程都关联一个 Job,该 Job 的生命周期与协程的生命周期同步。你可以通过调用 job.cancel() 来取消协程,或者使用 job.isActive 等属性来检查协程的状态。
3. CoroutineContext
CoroutineContext 是协程的上下文,它定义了协程的行为。一个 CoroutineContext 由多个元素组成:
- Job: 控制协程的生命周期。
- CoroutineDispatcher: 确定协程执行在哪个线程上。
- CoroutineName: 协程的名称,通常用于调试。
- CoroutineExceptionHandler: 处理未捕获的异常。
当创建一个协程时,它会有一个新的 Job 实例,该实例可以控制协程的生命周期。其他的元素(如调度器、异常处理器等)会从父级的 CoroutineContext 中继承。
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch {
// 新的协程,它的父级是 CoroutineScope
val result = async {
// 新的协程,它的父级是 launch
}.await()
}
在这个例子中,协程有一个父级 CoroutineContext,可以是 CoroutineScope 或另一个协程。创建的每个新协程都将继承父级的 CoroutineContext。
4. Job的生命周期
Job 的生命周期经历多个状态:
- New: 协程被创建但未启动。
- Active: 协程正在运行。
- Completing: 协程正在结束。
- Completed: 协程已完成。
- Cancelling: 协程正在被取消。
- Cancelled: 协程已取消。
尽管我们无法直接访问这些状态,但可以通过 Job 的一些属性来判断协程的状态:
isActive: 判断协程是否处于激活状态。isCancelled: 判断协程是否被取消。isCompleted: 判断协程是否完成。
例如,如果协程处于 Active 状态,执行失败或调用 job.cancel() 会将 Job 转为 Cancelling 状态。
5. 父级CoroutineContext
每个协程都有一个父级上下文,父级可以是 CoroutineScope 或另一个协程。然而,一个协程的 CoroutineContext 可以与父级的 CoroutineContext 不同。父级的 CoroutineContext 是基于以下公式计算的:
Parent context = Defaults + inherited CoroutineContext + arguments
- Defaults: 默认值,如
Dispatchers.Default是CoroutineDispatcher的默认值。 - Inherited CoroutineContext: 父级
CoroutineContext(即创建该协程的CoroutineScope或协程的CoroutineContext)。 - Arguments: 传递给协程构造器的参数优先于继承的元素。
例如:
val scope = CoroutineScope(Job() + Dispatchers.Main + coroutineExceptionHandler)
父级 CoroutineContext 将包含 Dispatchers.Main、默认的 "coroutine" 名称、Job 和异常处理器。
对于新创建的协程来说,它的 CoroutineContext 会是:
New coroutine context = parent CoroutineContext + Job()
例如:
val job = scope.launch(Dispatchers.IO) {
// 新的协程
}
在这个例子中,父级 CoroutineContext 中的 Dispatchers 是 Dispatchers.IO 而不是 Dispatchers.Main,因为它是通过协程构造器传递的参数来覆盖的。
6. 小结
本文介绍了协程的一些核心概念:CoroutineScope、Job 和 CoroutineContext。这些概念对于理解协程的生命周期和如何管理协程至关重要。
CoroutineScope用于创建协程,并跟踪其生命周期。Job是协程的句柄,提供了管理协程生命周期的能力。CoroutineContext是协程的上下文,定义了协程的行为,包括调度器、异常处理等。
🌟 关注我的CSDN博客,收获更多技术干货! 🌟
更多推荐
所有评论(0)