跳到主要内容

Kotlin 协程与线程调度

♾️ Kotlin 协程是 Android 异步编程的标准方式。正确使用 Dispatcher 和作用域是避免线程和内存问题的关键。

协程基础

主要组件

// CoroutineScope — 生命周期
// Dispatcher — 执行线程
// Job — 可取消的异步任务

scope.launch(Dispatchers.IO) {
val data = fetchData() // 运行在 IO 线程池
withContext(Dispatchers.Main) {
updateUI(data) // 切换到主线程
}
}

Dispatcher 类型

Dispatcher适用场景
Dispatchers.MainUI 操作、LiveData 更新
Dispatchers.IO文件、网络、数据库
Dispatchers.DefaultCPU 密集计算
Dispatchers.Unconfined不限制,测试用

ViewModel + 协程

class UserViewModel : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> = _users.asStateFlow()

fun loadUsers() {
viewModelScope.launch { // 随 ViewModel 自动取消
try {
val data = withContext(Dispatchers.IO) {
repository.getUsers()
}
_users.value = data
} catch (e: Exception) {
// 处理错误
}
}
}
}

结构化并发

// 并行执行多个请求
suspend fun loadAllData(): Pair<User, List<Post>> {
return coroutineScope {
val user = async { fetchUser() }
val posts = async { fetchPosts() }
Pair(user.await(), posts.await())
}
}

// 对试结果取最快的
val result = select<String> {
async { fetchFromPrimary() }.onAwait { it }
async { fetchFromBackup() }.onAwait { it }
}

Flow 与状态流

// 冷流(Cold Flow)——每次收集即重新执行
val coldFlow = flow {
emit(1)
delay(1000)
emit(2)
}

// 热流(Hot Flow)——多个收集器共享
val stateFlow = MutableStateFlow(0)
val sharedFlow = MutableSharedFlow<Event>()

// 在 Fragment 中安全收集
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}

StateFlow vs SharedFlow

StateFlowSharedFlow
初始值必须延迟默认无
重放最新值可配置 replay
适用场景UI 状态事件(导航、Toast)

取消与异常处理

val job = scope.launch {
try {
doWork()
} catch (e: CancellationException) {
throw e // 必须重抛,否则取消无法传播
} catch (e: Exception) {
handleError(e)
} finally {
cleanup() // 取消时也会执行
}
}

// 取消任务
job.cancel()

常见误区

  • Dispatchers.Main 中进行平常 IO 操作,阴塞主线程
  • 捕获 CancellationException 后没有重抛,导致取消失效
  • 在 Fragment/Activity 中使用 GlobalScope 而非 viewModelScope,生命周期不考模