第2章 Kotlin协程基础回顾:协程作用域、挂起函数、调度器

协程是 Android 中处理异步操作的标准方案,WorkManager 从 2.6.0 版本起原生支持协程。要在 WorkManager 中高效使用协程,必须掌握三个核心概念:协程作用域(管理协程生命周期)、挂起函数(非阻塞等待)和调度器(控制线程池)。本章快速回顾这些基础,聚焦于后续实战中频繁用到的模式。

2.1 协程作用域 (CoroutineScope)

每个协程都必须在某个 CoroutineScope 中启动,作用域决定了协程的存活周期。Android 中常用的作用域有:

作用域生命周期典型用途自动取消
GlobalScope进程级别一些全局常驻任务(极少使用)否
coroutineScope { }内部所有子协程完成挂起函数内并发由父协程控制
supervisorScope { }内部子协程独立失败一个任务失败不影响其他由父协程控制
viewModelScope (AndroidX)ViewModel 清除时ViewModel 内异步自动
lifecycleScope (AndroidX)Lifecycle 结束时Activity/Fragment 内协程自动
💡 最佳实践:WorkManager 的 Worker 内部使用 suspend fun doWork(),它已经运行在协程上下文中,由 WorkManager 提供作用域;不要在 Worker 内自己创建 GlobalScope。

2.2 挂起函数 (Suspend Functions)

挂起函数是协程的核心,可以暂停执行而不阻塞线程。声明使用 suspend 关键字:

suspend fun fetchData(): String {
    // 模拟网络请求
    delay(1000)
    return "Data loaded"
}

挂起函数只能在 协程 或 另一个挂起函数 中调用。常用内置挂起函数:delay()、withContext()、yield() 等。

⏱️ withContext 示例:切换调度器做耗时操作
suspend fun processImage(input: Bitmap): Bitmap = withContext(Dispatchers.Default) {
    // 密集计算
    input.copy(Bitmap.Config.ARGB_8888, false)
}

2.3 调度器 (Dispatchers)

调度器决定协程在哪个线程池中执行。常用调度器:

调度器线程池典型场景
Dispatchers.DefaultCPU 密集型 — 线程数 = 核心数 + 1图像处理、解析 JSON
Dispatchers.IOIO 密集型 — 线程数可能很大网络请求、文件读写、数据库操作
Dispatchers.MainAndroid 主线程UI 更新、点击回调
Dispatchers.Unconfined调用线程(不切换)测试或不需要特定线程时

切换调度器使用 withContext,如 withContext(Dispatchers.IO) { ... }。在 WorkManager 中,默认的 doWork() 运行在 Dispatchers.Default 上,但可以通过 withContext(Dispatchers.IO) 来处理 I/O 任务。

2.4 协程构建器

构建器返回失败传播典型用法
launchJob向父协程抛出“发起并忘记”
asyncDeferred<T>仅在 await() 时抛出并发获取多个结果
runBlocking阻塞调用线程直接抛出测试 / 桥接协程与非协程

在 WorkManager 的 doWork() 中,通常只需要挂起函数,不需要手动调用这些构建器;但如果需要并发执行多个任务,可以使用 coroutineScope 包裹 async。

2.5 结构化并发

结构化并发保证:父协程取消时所有子协程自动取消;子协程异常会按作用域规则传播。这是 Android 中避免泄漏和异常崩溃的关键。viewModelScope 和 lifecycleScope 已经内置了结构化并发。在 WorkManager 中,doWork() 本身就是一个挂起函数,其结构化由 WorkManager 内部管理,你只需关注 withContext 和自定义挂起函数的正确性。

⚠️ 常见错误:在非协程作用域(如回调或广播接收器中)直接调用挂起函数,会导致编译错误“Suspend function 'xxx' should be called only from a coroutine or another suspend function”。解决办法:通过 GlobalScope.launch 或合适的生命周期作用域启动协程,再调用挂起函数。
协程作用域、挂起函数、调度器关系图 结构化并发 (Structured Concurrency) CoroutineScope 作用域 Suspend Function 挂起函数 Dispatcher 调度器 Coroutine Builder (launch/async) WorkManager doWork() 内应用 结构化并发是基石:作用域提供生命周期,挂起函数写异步逻辑,调度器控制线程。 WorkManager 内置协程支持,你只需编写挂起函数并选择合适的调度器。