协程上下文
一、什么是协程上下文?
CoroutineContext
是一个协程的运行环境容器,决定协程的生命周期、运行线程、错误处理机制等核心行为。它由若干个元素组成。
常见元素及其作用:
元素类型 | 说明 |
---|---|
Job / SupervisorJob | 控制协程的生命周期、结构化并发 |
CoroutineDispatcher | 决定协程在哪个线程/线程池运行(如:Main , IO , Default ) |
CoroutineName | 用于日志标识与调试 |
CoroutineExceptionHandler | 捕获未处理的异常,防止崩溃 |
二、协程上下文的组合方式
上下文可以通过 +
进行组合,不同类型元素会被合并,相同类型后者覆盖前者。
kotlin
val context = Dispatchers.IO + SupervisorJob() + CoroutineName("OcrScope")
注意:组合顺序无影响,但同一类型(如两个
Dispatcher
)会后者覆盖前者。
三、实际应用场景分析
假设:OCR 实时翻译系统中,包含以下任务:
- 实时图像帧 OCR(IO 密集)
- 翻译文字(CPU 密集)
- UI 更新(主线程)
- 需要可取消/优先级切换/错误处理
推荐协程上下文组合
1. 任务作用域初始化
kotlin
val scope = CoroutineScope(
SupervisorJob() +
Dispatchers.Default +
CoroutineName("TranslateScope") +
CoroutineExceptionHandler { _, throwable ->
Log.e("TranslateScope", "Unhandled error: $throwable")
}
)
2. 使用示例:低优先级 OCR 翻译任务
kotlin
scope.launch {
val result = ocrClient.recognize(bitmap) // IO
val text = result.lines.joinToString("\n")
val translation = translator.translate(text) // CPU
withContext(Dispatchers.Main) {
updateUi(translation) // UI更新
}
}
四、不同上下文组合的实际对比
场景 | 组合方式 | 适合任务 |
---|---|---|
快速 UI 绑定 | Job() + Dispatchers.Main | 动画、按钮状态更新 |
网络/文件访问 | SupervisorJob() + Dispatchers.IO | Retrofit, 文件读写 |
多任务并发处理 | SupervisorJob() + Dispatchers.Default | 翻译、计算 |
强错误控制 | + CoroutineExceptionHandler {...} | 错误集中处理、防止崩溃 |
五、协程作用域的生命周期管理
ViewModel 中推荐这样:
kotlin
class MyViewModel : ViewModel() {
private val scope = viewModelScope + CoroutineName("MyViewModelScope")
fun launchTranslateJob(input: List<String>) {
scope.launch {
val translated = translate(input)
_translationResult.postValue(translated)
}
}
}
非 ViewModel 场景如自定义调度类:
kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
关闭资源:
kotlin
scope.cancel() // 清理所有任务
六、最佳实践总结
- 使用
SupervisorJob()
,避免子任务失败影响全局 - 任务调度用
Dispatchers.IO
和Dispatchers.Default
区分 IO 和 CPU 密集型 - 永远不要在主线程运行耗时任务
- 使用
CoroutineName
追踪调试大型项目 - 通过
CoroutineExceptionHandler
保证稳定性
七、附录:调度器说明表
调度器 | 特点 | 适合场景 |
---|---|---|
Dispatchers.Main | UI 线程 | 更新界面、交互响应 |
Dispatchers.IO | IO 优化线程池 | 网络、数据库、文件 IO |
Dispatchers.Default | CPU 密集线程池 | 算法、解析、计算、翻译 |
Dispatchers.Unconfined | 当前线程启动,协程恢复位置不固定 | 高级用法(如测试) |