渐进式编程课
KMP 目录
第 5 课2026.07.21

网络请求、数据库读取等操作不会立即完成。KMP 可以在共享代码中用协程统一描述这些异步任务,让 Android 和 iOS 复用同一套业务流程。

第 5 课:KMP 共享协程基础

  • 日期:2026-07-21
  • 课程序号:05
  • 知识点:在 commonMain 中用 suspend 表达异步任务

用途

网络请求、数据库读取等操作不会立即完成。KMP 可以在共享代码中用协程统一描述这些异步任务,让 Android 和 iOS 复用同一套业务流程。

核心概念

  • suspend 函数可以挂起并稍后恢复,不等于阻塞当前线程。
  • suspend 函数只能由另一个 suspend 函数或协程调用。
  • 共享业务层负责提供异步 API;调用方负责决定协程何时启动、何时取消。
  • 不要在共享仓库内部创建与页面生命周期脱节的全局协程。

示例代码

先在共享模块的 commonMain 中加入协程核心依赖。版本号应统一使用项目已有的版本目录或版本变量:

kotlin
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation(libs.kotlinx.coroutines.core)
        }
    }
}

commonMain/UserRepository.kt:

kotlin
import kotlinx.coroutines.delay

data class User(
    val id: Long,
    val name: String,
)

class UserRepository {
    suspend fun loadUser(): User {
        delay(300) // 模拟网络或数据库等待
        return User(id = 1L, name = "KMP Learner")
    }
}

Android 页面可以用自己的生命周期作用域调用:

kotlin
lifecycleScope.launch {
    val user = UserRepository().loadUser()
    println(user.name)
}

关键边界是:UserRepository 只暴露 suspend API,不持有页面的 CoroutineScope;页面销毁时,lifecycleScope 会负责取消任务。

5 分钟练习

给 UserRepository 增加一个 suspend fun loadGreeting(): String:等待 100 毫秒后返回 "Hello, KMP!"。

参考答案

kotlin
import kotlinx.coroutines.delay

class UserRepository {
    suspend fun loadGreeting(): String {
        delay(100)
        return "Hello, KMP!"
    }
}

调用它时仍应由外部已有的协程作用域启动任务,而不是在 loadGreeting() 内创建新的全局作用域。

与上一课的联系

上一课学习了用 commonTest 验证共享逻辑。本课开始引入异步共享逻辑;后续可以使用 runTest 测试 suspend 函数,并继续学习用 Flow 表达持续变化的数据流。