Kotlin 协程上下文 #
一、CoroutineContext 概述 #
协程上下文是一组元素的集合,定义了协程的行为。
1.1 主要元素 #
| 元素 | 说明 |
|---|---|
| Job | 协程作业 |
| Dispatcher | 调度器 |
| CoroutineName | 协程名称 |
| CoroutineExceptionHandler | 异常处理器 |
1.2 组合上下文 #
kotlin
val context = Dispatchers.IO + CoroutineName("MyCoroutine")
二、Dispatchers 调度器 #
2.1 Default #
CPU 密集型任务:
kotlin
launch(Dispatchers.Default) {
// 排序、过滤、计算等
val result = heavyComputation()
}
2.2 IO #
IO 密集型任务:
kotlin
launch(Dispatchers.IO) {
// 网络请求、文件操作、数据库操作
val data = fetchData()
}
2.3 Main #
主线程(UI 线程):
kotlin
launch(Dispatchers.Main) {
// UI 更新
textView.text = "Hello"
}
2.4 Unconfined #
不限制线程:
kotlin
launch(Dispatchers.Unconfined) {
println("Thread: ${Thread.currentThread().name}")
delay(100)
println("Thread: ${Thread.currentThread().name}") // 可能不同
}
2.5 自定义调度器 #
kotlin
val singleThreadDispatcher = newSingleThreadContext("MyThread")
val fixedDispatcher = newFixedThreadPoolContext(4, "MyPool")
launch(singleThreadDispatcher) {
// 在单线程执行
}
三、Job #
3.1 获取 Job #
kotlin
fun main() = runBlocking {
val job = launch {
delay(1000)
println("Completed")
}
println("isActive: ${job.isActive}")
println("isCompleted: ${job.isCompleted}")
}
3.2 Job 状态 #
kotlin
fun main() = runBlocking {
val job = launch {
delay(1000)
}
// 状态
job.isActive // 是否活跃
job.isCompleted // 是否完成
job.isCancelled // 是否取消
// 操作
job.cancel() // 取消
job.join() // 等待完成
job.cancelAndJoin() // 取消并等待
}
3.3 父子关系 #
kotlin
fun main() = runBlocking {
val parentJob = launch {
launch {
delay(1000)
println("Child 1")
}
launch {
delay(500)
println("Child 2")
}
}
parentJob.join() // 等待所有子协程完成
}
3.4 取消传播 #
kotlin
fun main() = runBlocking {
val parent = launch {
repeat(5) { i ->
launch {
delay(1000)
println("Child $i")
}
}
}
delay(1500)
parent.cancel() // 取消父协程,所有子协程也被取消
}
四、CoroutineScope #
4.1 创建作用域 #
kotlin
// 使用 CoroutineScope
val scope = CoroutineScope(Dispatchers.Default)
scope.launch {
println("Running in scope")
}
// 使用 MainScope(Android)
val mainScope = MainScope()
mainScope.launch {
// 在主线程执行
}
4.2 自定义作用域 #
kotlin
class MyService {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
fun doWork() {
scope.launch {
// 执行任务
}
}
fun destroy() {
scope.cancel() // 取消所有协程
}
}
4.3 lifecycleScope(Android) #
kotlin
class MyFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycleScope.launch {
// 生命周期感知
val data = fetchData()
view.textView.text = data
}
}
}
4.4 viewModelScope(Android) #
kotlin
class MyViewModel : ViewModel() {
fun loadData() {
viewModelScope.launch {
val data = repository.fetch()
_data.value = data
}
}
}
五、上下文切换 #
5.1 withContext #
kotlin
suspend fun loadData(): String {
// 切换到 IO 线程
return withContext(Dispatchers.IO) {
fetchData()
}
}
5.2 链式切换 #
kotlin
suspend fun process() {
withContext(Dispatchers.IO) {
// IO 操作
val data = fetchData()
withContext(Dispatchers.Default) {
// CPU 计算
process(data)
}
}
}
5.3 保留上下文 #
kotlin
suspend fun example() {
println("Current: ${coroutineContext[Job]}")
withContext(Dispatchers.IO) {
// Job 相同,Dispatcher 不同
println("Current: ${coroutineContext[Job]}")
}
}
六、CoroutineName #
6.1 命名协程 #
kotlin
fun main() = runBlocking {
launch(CoroutineName("Worker-1")) {
println("Running: ${coroutineContext[CoroutineName]}")
}
launch(CoroutineName("Worker-2")) {
println("Running: ${coroutineContext[CoroutineName]}")
}
}
6.2 调试 #
kotlin
fun main() = runBlocking {
launch(CoroutineName("DataLoader")) {
println("Loading data...")
}
}
// 使用 -Dkotlinx.coroutines.debug 启动调试
七、CoroutineExceptionHandler #
7.1 全局异常处理 #
kotlin
fun main() = runBlocking {
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught: $exception")
}
launch(handler) {
throw Exception("Error!")
}
}
7.2 在作用域中使用 #
kotlin
class MyService {
private val handler = CoroutineExceptionHandler { _, e ->
println("Error: ${e.message}")
}
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO + handler)
fun doWork() {
scope.launch {
throw Exception("Something went wrong")
}
}
}
八、实战示例 #
8.1 网络请求封装 #
kotlin
class Repository {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
suspend fun <T> safeApiCall(
apiCall: suspend () -> T
): Result<T> {
return try {
Result.success(apiCall())
} catch (e: Exception) {
Result.failure(e)
}
}
fun destroy() {
scope.cancel()
}
}
8.2 并发限制 #
kotlin
suspend fun <T, R> List<T>.mapConcurrent(
concurrency: Int,
transform: suspend (T) -> R
): List<R> = coroutineScope {
val semaphore = Semaphore(concurrency)
map { item ->
async {
semaphore.withPermit {
transform(item)
}
}
}.awaitAll()
}
九、最佳实践 #
9.1 选择合适的 Dispatcher #
kotlin
// IO 操作 → Dispatchers.IO
withContext(Dispatchers.IO) { }
// CPU 计算 → Dispatchers.Default
withContext(Dispatchers.Default) { }
// UI 更新 → Dispatchers.Main
withContext(Dispatchers.Main) { }
9.2 使用结构化并发 #
kotlin
// 推荐:使用作用域
class MyService {
private val scope = CoroutineScope(SupervisorJob())
fun cleanup() {
scope.cancel()
}
}
9.3 处理异常 #
kotlin
val handler = CoroutineExceptionHandler { _, e ->
log.error("Coroutine error", e)
}
scope.launch(handler) {
// 协程代码
}
十、总结 #
协程上下文要点:
| 元素 | 说明 |
|---|---|
| Dispatchers | 线程调度 |
| Job | 协程作业 |
| CoroutineName | 协程名称 |
| CoroutineExceptionHandler | 异常处理 |
下一步,让我们学习 协程取消与超时!
最后更新:2026-03-27