LESSON 12

协程入门

并发工作,不把界面卡住

概念 · 示例 · 练习 · 小测
预计 12 分钟Android Studio

先用人话理解

协程是 Kotlin 中组织异步任务的方式。suspend 表示函数可以挂起等待;launch 启动不直接返回结果的任务,async 启动并通过 await 获取结果。Android 中不要在主线程执行阻塞式网络请求。

本课要点:Dispatchers.IO 适合阻塞式 I/O 工作;Dispatchers.Main 用于界面交互。lifecycleScope 会随生命周期结束而取消相关协程。

代码例子

先读注释,再关注每一行如何把数据变成结果。

KOTLIN/JVM · 需要协程依赖
// 需要 kotlinx-coroutines-core 依赖;可在普通 Kotlin/JVM Gradle 项目中运行
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

suspend fun loadProfile(): String {
    delay(300) // 模拟等待,不会阻塞协程所在的线程
    return "用户资料"
}

suspend fun loadOrders(): String {
    delay(300)
    return "订单列表"
}

fun main() = runBlocking {
    val (profile, orders) = coroutineScope {
        val profileTask = async { loadProfile() }
        val ordersTask = async { loadOrders() }
        profileTask.await() to ordersTask.await() // 两个任务并发启动
    }
    println(profile)
    println(orders)
}

再看一个用法

ANDROID · lifecycleScope
// Android 示例:需要 kotlinx-coroutines-android,以及 Activity/Fragment 的 lifecycleScope
lifecycleScope.launch {
    val (profile, orders) = coroutineScope {
        val profileTask = async(Dispatchers.IO) { repository.loadProfile() }
        val ordersTask = async(Dispatchers.IO) { repository.loadOrders() }
        profileTask.await() to ordersTask.await()
    }
    render(profile, orders) // launch 默认回到 Main,可在这里更新界面
}

动手改一改

把 loadOrders() 的返回文本改成“收藏列表”,再运行 main(),确认两个任务都能返回结果。

运行要求:这是 Kotlin/JVM + kotlinx-coroutines 示例,不是 Android 模拟器项目。普通 JVM 项目的 dependencies 中添加 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0");Android 项目使用 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.11.0"),并按项目的 Kotlin 版本核对兼容性。
查看协程官方文档 ↗

三道小测

先自己选择,再展开答案。答错也没关系,重要的是知道为什么。

1. suspend 表示什么?

查看答案与解析

正确答案:B。抓住题目中的核心概念,重新对照示例理解。

2. async 的结果通常如何取得?

查看答案与解析

正确答案:A。回到概念和代码示例,再解释一次为什么。

3. Android 网络 I/O 通常适合哪个调度器?

查看答案与解析

正确答案:B。抓住题目中的核心概念,重新对照示例理解。

深入阅读

想继续往下挖,可以阅读 Kotlin / Android 官方文档。

打开官方文档 ↗

标记学习进度

进度保存在当前浏览器的 localStorage 中。