Kotlin协程 #

一、协程基础 #

1.1 什么是协程 #

协程是一种轻量级的线程,可以在代码中实现异步逻辑的同步写法,避免回调地狱。

1.2 添加依赖 #

kotlin
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}

1.3 第一个协程 #

kotlin
fun main() = runBlocking {
    launch {
        delay(1000)
        println("World!")
    }
    println("Hello,")
}

二、协程构建器 #

2.1 launch #

kotlin
val job = GlobalScope.launch {
    delay(1000)
    println("Hello")
}

job.join()  // 等待协程完成
job.cancel()  // 取消协程

2.2 async #

kotlin
val deferred = GlobalScope.async {
    delay(1000)
    "Result"
}

val result = deferred.await()  // 获取结果

2.3 withContext #

kotlin
withContext(Dispatchers.IO) {
    // 切换到IO线程执行
    val data = fetchData()
    data
}

2.4 runBlocking #

kotlin
runBlocking {
    // 阻塞当前线程,直到协程完成
    delay(1000)
}

三、调度器 #

3.1 调度器类型 #

kotlin
// Default:CPU密集型任务
launch(Dispatchers.Default) {
    // 计算
}

// IO:IO密集型任务
launch(Dispatchers.IO) {
    // 网络、文件操作
}

// Main:主线程(Android)
launch(Dispatchers.Main) {
    // UI操作
}

// Unconfined:不指定线程
launch(Dispatchers.Unconfined) {
    // 不推荐使用
}

3.2 切换调度器 #

kotlin
lifecycleScope.launch {
    // 主线程
    showLoading()
    
    // 切换到IO线程
    val data = withContext(Dispatchers.IO) {
        fetchData()
    }
    
    // 回到主线程
    showData(data)
}

四、协程作用域 #

4.1 作用域类型 #

kotlin
// GlobalScope:全局作用域(不推荐)
GlobalScope.launch { }

// CoroutineScope:自定义作用域
val scope = CoroutineScope(Dispatchers.Main)
scope.launch { }

// lifecycleScope:生命周期作用域(Android)
lifecycleScope.launch { }

// viewModelScope:ViewModel作用域(Android)
viewModelScope.launch { }

4.2 SupervisorJob #

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

scope.launch {
    // 子协程失败不会影响其他子协程
    launch { }
    launch { }
}

4.3 coroutineScope #

kotlin
suspend fun loadData() = coroutineScope {
    launch {
        // 子协程1
    }
    launch {
        // 子协程2
    }
}

五、协程取消 #

5.1 取消协程 #

kotlin
val job = scope.launch {
    repeat(1000) {
        delay(100)
        println(it)
    }
}

delay(500)
job.cancel()
job.join()  // 或 job.cancelAndJoin()

5.2 检查取消状态 #

kotlin
val job = scope.launch {
    repeat(1000) {
        if (isActive) {  // 检查是否活跃
            // 执行任务
        }
        
        // 或使用ensureActive
        ensureActive()
    }
}

5.3 try-finally #

kotlin
val job = scope.launch {
    try {
        repeat(1000) {
            delay(100)
            println(it)
        }
    } finally {
        // 清理资源
        println("Cleanup")
    }
}

job.cancelAndJoin()

5.4 不可取消的代码块 #

kotlin
val job = scope.launch {
    try {
        repeat(1000) {
            delay(100)
            println(it)
        }
    } finally {
        withContext(NonCancellable) {
            // 这里的代码不会被取消
            delay(100)
            println("Cleanup")
        }
    }
}

六、Flow #

6.1 创建Flow #

kotlin
fun getNumbers(): Flow<Int> = flow {
    for (i in 1..10) {
        delay(100)
        emit(i)
    }
}

6.2 收集Flow #

kotlin
lifecycleScope.launch {
    getNumbers().collect { number ->
        println(number)
    }
}

6.3 Flow操作符 #

kotlin
lifecycleScope.launch {
    getNumbers()
        .map { it * 2 }  // 映射
        .filter { it > 5 }  // 过滤
        .take(3)  // 取前3个
        .collect { println(it) }
}

6.4 StateFlow #

kotlin
class MainViewModel : ViewModel() {
    
    private val _state = MutableStateFlow<UiState>(UiState.Loading)
    val state: StateFlow<UiState> = _state.asStateFlow()
    
    fun loadData() {
        viewModelScope.launch {
            _state.value = UiState.Loading
            try {
                val data = repository.getData()
                _state.value = UiState.Success(data)
            } catch (e: Exception) {
                _state.value = UiState.Error(e.message)
            }
        }
    }
}

// 在Activity中观察
lifecycleScope.launch {
    viewModel.state.collect { state ->
        when (state) {
            is UiState.Loading -> showLoading()
            is UiState.Success -> showData(state.data)
            is UiState.Error -> showError(state.message)
        }
    }
}

6.5 SharedFlow #

kotlin
class EventBus {
    private val _events = MutableSharedFlow<Event>()
    val events: SharedFlow<Event> = _events.asSharedFlow()
    
    suspend fun send(event: Event) {
        _events.emit(event)
    }
}

// 发送事件
eventBus.send(Event.Message("Hello"))

// 接收事件
lifecycleScope.launch {
    eventBus.events.collect { event ->
        handleEvent(event)
    }
}

七、异常处理 #

7.1 try-catch #

kotlin
scope.launch {
    try {
        val result = withContext(Dispatchers.IO) {
            fetchData()
        }
    } catch (e: Exception) {
        handleError(e)
    }
}

7.2 CoroutineExceptionHandler #

kotlin
val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}

scope.launch(handler) {
    throw RuntimeException("Error")
}

7.3 async异常 #

kotlin
scope.launch {
    val deferred = async {
        throw RuntimeException("Error")
    }
    
    try {
        deferred.await()
    } catch (e: Exception) {
        println("Caught $e")
    }
}

八、最佳实践 #

8.1 使用结构化并发 #

kotlin
// 推荐:使用作用域
lifecycleScope.launch {
    // 自动管理生命周期
}

// 不推荐:使用GlobalScope
GlobalScope.launch {
    // 不会自动取消
}

8.2 使用suspend函数 #

kotlin
suspend fun loadData(): Data {
    return withContext(Dispatchers.IO) {
        // 网络请求
        fetchData()
    }
}

8.3 避免阻塞 #

kotlin
// 不推荐
suspend fun bad() {
    Thread.sleep(1000)  // 阻塞线程
}

// 推荐
suspend fun good() {
    delay(1000)  // 不阻塞线程
}

九、总结 #

本章详细介绍了Kotlin协程:

  1. 协程的基本概念
  2. 协程构建器
  3. 调度器
  4. 协程作用域
  5. 协程取消
  6. Flow的使用
  7. 异常处理
  8. 最佳实践

协程是Kotlin最重要的特性之一,掌握协程对于Android开发至关重要。

最后更新:2026-03-26