Coroutine Builder:什么是它,协程构建器类型及工作原理

作者: IT Sectr 发布日期: 2026-06-21 阅读时间: 8 分钟

Coroutine Builder — 是 Kotlin Coroutines 的函数,用于创建和启动协程,并确定其执行方式。launch、async、runBlocking 和 produce 构建器覆盖了不同的场景:从后台任务到带结果返回的并行计算。根据 JetBrains, 2024 的数据,Coroutine Builder 是协程模型的基础,提供了结构化并发和生命周期管理。

要点

  • Coroutine Builder — 在特定 CoroutineScope 中创建协程的函数
  • launch — 启动协程而不返回结果,返回 Job 对象
  • async — 启动协程并返回 Deferred,允许通过 await() 获取结果
  • runBlocking — 阻塞当前线程,用作 blocking 和 suspending 代码之间的桥梁
  • produce — 创建带有通道的协程以进行流式数据传输(已废弃,推荐使用 Flow)

什么是 Coroutine Builder?

Coroutine Builder — 是一个 Kotlin 扩展函数,它接受 CoroutineScope 和 suspend 块,创建并启动一个新的协程。每个构建器确定协程的执行方式:带或不带结果返回,通过阻塞线程或异步方式。构建器是语言协程模型的入口点。

所有构建器通过 CoroutineScope 工作,后者管理子协程的生命周期。当 scope 被取消时,通过它启动的所有协程都会被自动取消 — 这是结构化并发的原则。这种方法防止了协程泄漏,并保证了可预测的完成。

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    // 构建器在 CoroutineScope 内运行
    val job = launch {
        delay(1000L)
        println("世界!")
    }
    println("你好,")
    job.join()
}

协程构建器的主要类型

Kotlin 提供了四个内置的协程构建器:launchasyncrunBlockingproduce。每个都有自己的返回类型和应用领域。对于 Android 移动开发,主要的是 launch 和 async — 它们以非阻塞方式工作,并与架构组件集成。

构建器返回类型线程阻塞场景
launchJobFire-and-forget 任务
asyncDeferred<T>并行计算
runBlockingT测试、main 函数
produceReceiveChannel<E>流式传输(已废弃)

每个构建器接受额外的参数:CoroutineStart(启动策略)、CoroutineContext(调度器、异常)和命名的代码块。默认情况下,协程立即启动(CoroutineStart.DEFAULT)。

launch:fire-and-forget 启动

launch — 在 Android 开发中最常用的构建器。它启动一个不返回结果的协程,并返回一个 Job 对象来管理其生命周期。这是需要副作用的操作的理想选择:保存到数据库、发送分析数据、更新 UI。

launch 的语法和使用

launch 构建器接受 CoroutineScope、可选的 CoroutineContext 和 suspend 块。返回的 Job 允许取消协程、等待其完成或检查状态。

kotlin
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val job: Job = scope.launch(CoroutineStart.LAZY) {
    val data = fetchFromNetwork()
    saveToDatabase(data)
}
job.start()
job.join()

CoroutineStart.LAZY 参数将启动延迟到显式调用 start() 或 join()。这对于延迟初始化和条件启动很有用。对于标准的立即启动,使用 CoroutineStart.DEFAULT 或省略参数。

async:带结果的并行计算

async — 返回 Deferred<T> 的构建器 — 结果的异步承诺。await() 调用会暂停协程直到获得结果,而不会阻塞线程。这是 Kotlin 协程中并行任务的主要机制。

并行启动两个请求

当需要同时执行多个独立操作时,async 特别有效。与顺序调用 suspend 函数不同,async 并行启动协程,从而缩短总执行时间

kotlin
suspend fun fetchUserData(): UserData {
    val deferred1 = CoroutineScope(Dispatchers.IO).async { api.getProfile() }
    val deferred2 = CoroutineScope(Dispatchers.IO).async { api.getSettings() }
    val deferred3 = CoroutineScope(Dispatchers.IO).async { api.getNotifications() }
    return UserData(
        profile = deferred1.await(),
        settings = deferred2.await(),
        notifications = deferred3.await()
    )
}

Deferred 继承自 Job,因此 async 支持所有生命周期操作:取消、等待完成、异常处理。当 scope 被取消时,子 Deferred 协程会自动被取消。

runBlocking:通往 blocking 世界的桥梁

runBlocking — 是唯一一个阻塞当前线程直到协程完成的构建器。它创建一个新的 CoroutineScope 并启动传递的协程,同时阻塞调用线程。用于 main() 入口点、测试以及与 blocking 代码的集成。

何时需要 runBlocking

runBlocking 在三种场景下是合理的:应用程序入口点(main)、suspend 函数的单元测试以及与基于回调的库集成(无法使用 suspend)。在 Android 生产代码中,在主线程上使用 runBlocking 强烈不建议

kotlin
class CoroutineTest {
    @Test
    fun `test suspend function`() = runBlocking {
        val result = mySuspendFunction()
        assertEquals("expected", result)
    }
}

对于测试,建议使用 kotlinx-coroutines-test 与 TestCoroutineDispatcher 代替 runBlocking — 这提供了时间控制,并避免了测试环境中的阻塞。

如何选择合适的构建器

Coroutine Builder 的选择取决于返回结果和执行场景。如果操作不需要返回数据 — 使用 launch。如果需要异步操作的结果 — async。runBlocking 仅用于 bridging,而 produce 应替换为 Flow 以用于响应式流。

针对 Android 的实用建议

在使用 Kotlin Coroutines 的 Android 项目中,主要的构建器对是 launch 和 async。launch 在 ViewModel 和 UseCases 中用于启动协程,而 async 用于对网络或数据库的并行请求。现代库(Ktor、Room)已经支持 suspend 函数,这最大限度地减少了直接使用 async 的需求。

  • launch — 用于 fire-and-forget(日志记录、分析、缓存)
  • async — 用于带结果合并的并行请求
  • runBlocking — 仅用于 main() 和测试(不在生产环境的主线程上)
  • produce — 替换为 Flow / SharedFlow / StateFlow

常见问题

Kotlin 中 launch 和 async 有什么区别?

launch 返回 Job 且不返回执行结果,而 async 返回 Deferred<T> — 一个可以从中通过 await() 获取结果的对象。launch 用于 fire-and-forget 操作,async 用于返回数据的任务。

可以在 Android Activity 中使用 runBlocking 吗?

不建议。runBlocking 在主线程上会导致 ANR 并阻塞 UI。在 Activity 和 Fragment 内部使用 lifecycleScope.launch — 这是无阻塞的内置解决方案。

launch 构建器返回什么?

launch 构建器返回一个 Job 对象,允许您控制协程的生命周期:取消(cancel)、等待完成(join)、检查状态(isActive、isCompleted、isCancelled)。

Kotlin Coroutines 中的 Deferred 是什么?

Deferred<T> — 是 async 构建器返回的异步结果承诺。它继承自 Job,并添加了用于获取结果的 await() 方法、用于非阻塞访问的 getCompleted() 方法和用于检查异常的 getCompletionExceptionOrNull() 方法。

如何延迟启动 launch?

使用 CoroutineStart.LAZY 参数:scope.launch(start = CoroutineStart.LAZY) { ... }。然后调用 job.start() 或 job.join() 进行实际启动。这对于延迟初始化和协程的条件执行很有用。

总结

  • Coroutine Builder — 创建协程的函数,确定其执行方式和返回类型
  • launch — 用于不返回结果的任务的主要构建器,返回 Job 以管理协程
  • async — 用于并行计算的构建器,返回 Deferred 并具有 await() 结果的能力
  • runBlocking — 用于 main() 和测试的阻塞构建器,不建议在 Android 主线程上使用
  • 结构化并发 保证了 scope 取消时子协程的自动取消
  • produce 已废弃 — 使用 Flow、SharedFlow 或 StateFlow 进行响应式数据流
  • 构建器的选择取决于场景:fire-and-forget → launch,并行数据 → async,bridging → runBlocking

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读