跳转到正文
YGJoon 技术博客

Android Kotlin 协程基础与调度器

发布于:
·1.1k 字 · 约 3 分钟·作者:
Kotlin 协程地基:launch/async、Dispatcher 线程切换、结构化并发的取消传播,从 Dart async 视角对比理解更顺。
Android Kotlin 协程基础与调度器文章封面
目录

核心概念速览

suspend fun fetchUser(): User {
    return apiService.getUser()
}

GlobalScope.launch {
    val user = fetchUser()
    println(user)
}

实际 Android 开发不推荐使用 GlobalScope,请使用生命周期感知的作用域。

协程作用域

作用域用途
GlobalScope全局生命周期,避免使用
lifecycleScopeLifecycleOwner(Activity/Fragment)
viewModelScopeViewModel 生命周期
CoroutineScope 自定义业务层自定义生命周期
class MainViewModel : ViewModel() {
    fun load() = viewModelScope.launch {
        val data = repository.fetch()
        _uiState.value = data
    }
}

调度器与线程切换

调度器描述场景
Dispatchers.Main主线程,UI 更新更新 UI、Compose 状态
Dispatchers.IOIO 密集任务网络请求、磁盘操作
Dispatchers.DefaultCPU 密集任务解析 JSON、加密运算
Dispatchers.Unconfined不限制线程,谨慎使用调试、测试
lifecycleScope.launch(Dispatchers.IO) {
    val result = api.getArticles()
    withContext(Dispatchers.Main) {
        render(result)
    }
}

协程构建器

val user = async { repository.fetchUser() }
val posts = async { repository.fetchPosts() }
val homeData = awaitAll(user, posts)

异常处理

val handler = CoroutineExceptionHandler { _, throwable ->
    Timber.e(throwable, "coroutine error")
}

viewModelScope.launch(handler) {
    try {
        repository.fetch()
    } catch (e: IOException) {
        _uiState.value = UiState.Error(e)
    }
}

结构化并发

suspend fun refreshData() = coroutineScope {
    val userDeferred = async { repository.fetchUser() }
    val feedDeferred = async { repository.fetchFeed() }
    val user = userDeferred.await()
    val feed = feedDeferred.await()
    user to feed
}

协程与传统回调的对比

特点回调方式协程方式
可读性回调地狱线性代码
错误处理需逐层捕获结构化并发统一处理
资源释放容易泄漏作用域取消自动释放

常见误区

实战案例:从 Dart 视角看 Dispatcher

我是 Flutter 开发者,第一次写 Kotlin 协程时,最大的思维转换就是 Dispatcher——Dart 里根本没有这个概念。

Dart 是单线程事件循环:async/await 写完就完事,IO 操作自动丢给系统线程池,compute() 才需要手动开 Isolate。而 Kotlin 里,你必须显式决定协程跑在哪:Dispatchers.Main 更新 UI,Dispatchers.IO 做网络,Dispatchers.Default 做计算。选错了的后果很直接——我在看官方文档的 dispatcher 章节时注意到,Dispatchers.IO 和 Default 共享线程池但上限不同(IO 默认 64 线程,Default 是 CPU 核数),把 JSON 解析这种 CPU 活丢到 IO 线程池,等于在跟网络请求抢线程。

另一个坑是 GlobalScope。Dart 里没有”作用域”概念,Future 扔出去就不管了;Kotlin 里 GlobalScope.launch 是官方文档明确反对的写法——协程泄漏不会像 Dart 那样随 Isolate 结束而消失,它会一直占着。Android 里永远用 lifecycleScope / viewModelScope,让生命周期替你取消。

一句话总结:Dart 的并发是”省心但粗”,Kotlin 协程是”精细但要操心”。理解了 Dispatcher 这层,协程就入门了。

参考:Kotlin 官方文档 Coroutine dispatchers 章节(kotlinlang.org)

总结

  1. 协程提供轻量级并发机制,通过作用域与调度器管理生命周期和线程。
  2. 结构化并发有助于统一错误处理并避免资源泄漏。
  3. 掌握 launch、async、withContext 等常用构建器,是进阶 Flow 与 Compose 的基础。

下一篇将把协程应用到 Android 实战,涵盖网络请求、Room 与 UI 协同。


分享这篇文章:


相关文章

上一篇
Android Kotlin 集合操作与标准库实战
下一篇
Android Kotlin Flow 数据流与状态管理