Kotlin 协程与线程调度
♾️ Kotlin 协程是 Android 异步编程的标准方式。正确使用 Dispatcher 和作用域是避免线程和内存问题的关键。
协程基础
主要组件
// CoroutineScope — 生命周期
// Dispatcher — 执行线程
// Job — 可取消的异步任务
scope.launch(Dispatchers.IO) {
val data = fetchData() // 运行在 IO 线程池
withContext(Dispatchers.Main) {
updateUI(data) // 切换到主线程
}
}
Dispatcher 类型
| Dispatcher | 适用场景 |
|---|---|
Dispatchers.Main | UI 操作、LiveData 更新 |
Dispatchers.IO | 文件、网络、数据库 |
Dispatchers.Default | CPU 密集计算 |
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
| StateFlow | SharedFlow | |
|---|---|---|
| 初始值 | 必须 | 延迟默认无 |
| 重放 | 最新值 | 可配置 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,生命周期不考模