CoroutineContext
是 Kotlin 协程(Coroutine) 的核心概念之一,用来描述协程的运行环境 、调度器 、异常处理 、Job层级关系等信息。
🧩 一、定义
在 Kotlin 中,CoroutineContext
是一个接口:
kotlin
public interface CoroutineContext {
operator fun <E : Element> get(key: Key<E>): E?
operator fun plus(context: CoroutineContext): CoroutineContext
interface Key<E : Element>
interface Element : CoroutineContext
}
通俗讲:
👉 CoroutineContext
是一组「键值对」组成的集合,用于描述协程的运行配置。
🧠 二、常见的 CoroutineContext 元素
元素类型 | 作用 | 示例 |
---|---|---|
Job |
控制协程的生命周期(启动、取消、完成) | launch { } 自动创建一个 Job |
CoroutineDispatcher |
决定协程运行在哪个线程或线程池 | Dispatchers.IO , Dispatchers.Main , Dispatchers.Default |
CoroutineName |
给协程命名,方便调试 | CoroutineName("MyCoroutine") |
CoroutineExceptionHandler |
处理未捕获的异常 | CoroutineExceptionHandler { _, e -> println(e) } |
每个都是 CoroutineContext.Element
。
🧮 三、组合(+
运算)
你可以通过 +
将多个 context 元素合并成一个:
scss
val context = Dispatchers.IO + CoroutineName("Worker") + Job()
当你启动协程时:
scss
val scope = CoroutineScope(context)
scope.launch {
println("Running in ${coroutineContext[CoroutineName]}")
}
coroutineContext
是当前协程实际运行的上下文,它会继承并合并 scope
的 context 与当前协程的 context。
⚙️ 四、继承关系与上下文传播
协程会从父协程继承上下文的一部分:
scss
val parent = CoroutineScope(Dispatchers.Default + Job())
parent.launch(CoroutineName("Child")) {
println(coroutineContext[Job]) // 继承了父 Job
println(coroutineContext[CoroutineDispatcher]) // 继承 Dispatchers.Default
}
✅ 注意:
- 子协程的
Job
会是父协程Job
的子层级。- 如果显式指定了
Dispatcher
,会替换父的。
🧰 五、在协程中访问当前上下文
scss
launch {
println(coroutineContext[Job])
println(coroutineContext[CoroutineDispatcher])
println(coroutineContext[CoroutineName])
}
🧨 六、实际应用例子
例 1:指定运行线程
javascript
launch(Dispatchers.IO) {
// 在IO线程执行
}
例 2:添加协程名 + 异常处理
javascript
val handler = CoroutineExceptionHandler { _, e ->
println("Caught: $e")
}
launch(Dispatchers.Default + CoroutineName("MainTask") + handler) {
println("Running ${coroutineContext[CoroutineName]}")
throw RuntimeException("Oops")
}
🌳 七、总结图示
scss
CoroutineContext
├── Job // 控制协程生命周期
├── CoroutineDispatcher // 决定线程/调度器
├── CoroutineName // 协程命名
├── CoroutineExceptionHandler // 异常处理
└── (可自定义元素)
