Coroutine Builder: nó là gì, các loại trình xây dựng coroutine và cách chúng hoạt động

Tác giả: IT Sectr Đã đăng: 2026-06-21 Thời gian đọc: 8 phút

Coroutine Builder — các hàm của Kotlin Coroutines tạo và chạy coroutine, xác định cách chúng thực thi. Các trình xây dựng launch, async, runBlocking và produce bao phủ nhiều kịch bản khác nhau: từ tác vụ nền đến tính toán song song có trả về kết quả. Theo JetBrains, 2024, Coroutine Builder là nền tảng của mô hình coroutine, cung cấp khả năng đồng thời có cấu trúc và quản lý vòng đời.

Những điểm chính

  • Coroutine Builder — một hàm tạo coroutine trong một CoroutineScope cụ thể
  • launch — chạy coroutine mà không trả về kết quả, trả về đối tượng Job
  • async — chạy coroutine trả về Deferred, cho phép lấy kết quả qua await()
  • runBlocking — chặn luồng hiện tại, được dùng làm cầu nối giữa code chặn và code treo
  • produce — tạo coroutine với kênh để truyền phát dữ liệu (không được khuyến khích, thay bằng Flow)

Coroutine Builder là gì?

Coroutine Builder là một hàm mở rộng của Kotlin nhận CoroutineScope và một khối suspend, tạo và chạy một coroutine mới. Mỗi trình xây dựng xác định cách coroutine sẽ thực thi: có hoặc không trả về kết quả, có chặn luồng hoặc bất đồng bộ. Các trình xây dựng là điểm vào của mô hình coroutine trong ngôn ngữ.

Tất cả các trình xây dựng hoạt động thông qua CoroutineScope, quản lý vòng đời của các coroutine con. Khi một phạm vi bị hủy, tất cả coroutine được chạy qua nó sẽ tự động bị hủy — đây là nguyên tắc của đồng thời có cấu trúc. Cách tiếp cận này ngăn chặn rò rỉ coroutine và đảm bảo kết thúc có thể dự đoán trước.

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    // Các trình xây dựng chạy bên trong CoroutineScope
    val job = launch {
        delay(1000L)
        println("Thế giới!")
    }
    println("Xin chào,")
    job.join()
}

Các loại trình xây dựng coroutine chính

Kotlin cung cấp bốn trình xây dựng coroutine tích hợp: launch, async, runBlockingproduce. Mỗi loại có kiểu trả về và phạm vi ứng dụng riêng. Đối với phát triển di động Android, các trình xây dựng chính là launch và async — chúng hoạt động không chặn và tích hợp với các thành phần kiến trúc.

Trình xây dựngKiểu trả vềChặn luồngKịch bản
launchJobKhôngTác vụ fire-and-forget
asyncDeferred<T>KhôngTính toán song song
runBlockingTKiểm thử, hàm main
produceReceiveChannel<E>KhôngTruyền phát (không khuyến khích)

Mỗi trình xây dựng chấp nhận các tham số bổ sung: CoroutineStart (chiến lược khởi chạy), CoroutineContext (bộ điều phối, ngoại lệ) và một khối code có tên. Theo mặc định, coroutine bắt đầu ngay lập tức (CoroutineStart.DEFAULT).

launch: thực thi fire-and-forget

launch là trình xây dựng được sử dụng nhiều nhất trong phát triển Android. Nó chạy một coroutine không trả về kết quả và trả về đối tượng Job để quản lý vòng đời của nó. Đây là lựa chọn lý tưởng cho các thao tác chỉ cần hiệu ứng phụ: lưu vào cơ sở dữ liệu, gửi phân tích, cập nhật giao diện.

Cú pháp và cách sử dụng launch

Trình xây dựng launch chấp nhận CoroutineScope, một CoroutineContext tùy chọn và một khối suspend. Job được trả về cho phép hủy coroutine, chờ hoàn thành hoặc kiểm tra trạng thái.

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

Tham số CoroutineStart.LAZY hoãn thực thi cho đến khi gọi start() hoặc join() một cách tường minh. Điều này hữu ích cho khởi tạo trễ và thực thi có điều kiện. Để thực thi tức thời tiêu chuẩn, sử dụng CoroutineStart.DEFAULT hoặc bỏ qua tham số.

async: tính toán song song có kết quả

async là trình xây dựng trả về Deferred<T> — một lời hứa bất đồng bộ về kết quả. Gọi await() tạm dừng coroutine cho đến khi nhận được kết quả mà không chặn luồng. Đây là cơ chế chính cho các tác vụ song song trong coroutine Kotlin.

Chạy hai yêu cầu song song

async đặc biệt hiệu quả khi bạn cần thực thi nhiều thao tác độc lập đồng thời. Không giống như gọi tuần tự các hàm suspend, async chạy coroutine song song, giảm tổng thời gian thực thi.

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 kế thừa từ Job, do đó async hỗ trợ tất cả các thao tác vòng đời: hủy bỏ, chờ hoàn thành, xử lý ngoại lệ. Khi một phạm vi bị hủy, các coroutine Deferred con tự động bị hủy.

runBlocking: cầu nối đến thế giới chặn

runBlocking là trình xây dựng duy nhất chặn luồng hiện tại cho đến khi coroutine hoàn thành. Nó tạo một CoroutineScope mới và chạy coroutine được truyền vào, chặn luồng gọi. Nó được sử dụng trong các điểm vào main(), trong kiểm thử và khi tích hợp với code chặn.

Khi nào runBlocking cần thiết

runBlocking được biện minh trong ba kịch bản: điểm vào ứng dụng (main), kiểm thử đơn vị các hàm suspend và tích hợp với các thư viện dựa trên callback không thể dùng suspend. Trong code Android sản xuất, sử dụng runBlocking trên luồng chính không được khuyến khích.

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

Đối với kiểm thử, nên sử dụng kotlinx-coroutines-test với TestCoroutineDispatcher thay vì runBlocking — điều này cung cấp khả năng kiểm soát thời gian và tránh chặn trong môi trường kiểm thử.

Cách chọn trình xây dựng phù hợp

Việc chọn Coroutine Builder phụ thuộc vào kết quả trả về và kịch bản thực thi. Nếu thao tác không yêu cầu trả về dữ liệu — hãy sử dụng launch. Nếu bạn cần kết quả của một thao tác bất đồng bộ — hãy sử dụng async. Chỉ sử dụng runBlocking để làm cầu nối và thay thế produce bằng Flow cho các luồng phản ứng.

Khuyến nghị thực tế cho Android

Trong các dự án Android sử dụng Kotlin Coroutines, cặp trình xây dựng chính là launch và async. launch được sử dụng trong ViewModel và UseCases để chạy coroutine, trong khi async được sử dụng cho các yêu cầu song song đến mạng hoặc cơ sở dữ liệu. Các thư viện hiện đại (Ktor, Room) đã hỗ trợ các hàm suspend, điều này giảm thiểu nhu cầu sử dụng async trực tiếp.

  • launch — cho fire-and-forget (ghi log, phân tích, lưu cache)
  • async — cho các yêu cầu song song với kết hợp kết quả
  • runBlocking — chỉ trong main() và kiểm thử (không trên luồng Main trong sản xuất)
  • produce — thay thế bằng Flow / SharedFlow / StateFlow

Câu hỏi thường gặp

Sự khác biệt giữa launch và async trong Kotlin là gì?

launch trả về Job và không trả về kết quả thực thi, trong khi async trả về Deferred<T> — một đối tượng mà từ đó có thể lấy kết quả qua await(). launch được dùng cho các thao tác fire-and-forget, async dùng cho các tác vụ trả về dữ liệu.

Có thể sử dụng runBlocking trong Activity Android không?

Không được khuyến khích. runBlocking trên luồng chính gây ANR và chặn giao diện. Hãy sử dụng lifecycleScope.launch bên trong Activity và Fragment — đó là giải pháp tích hợp không chặn.

Trình xây dựng launch trả về gì?

Trình xây dựng launch trả về một đối tượng Job, cho phép kiểm soát vòng đời coroutine: hủy (cancel), chờ hoàn thành (join), kiểm tra trạng thái (isActive, isCompleted, isCancelled).

Deferred trong Kotlin Coroutines là gì?

Deferred<T> là một lời hứa bất đồng bộ về kết quả, được trả về bởi trình xây dựng async. Nó kế thừa từ Job và thêm các phương thức: await() để lấy kết quả, getCompleted() để truy cập không chặn và getCompletionExceptionOrNull() để kiểm tra ngoại lệ.

Làm thế nào để chạy launch với độ trễ?

Sử dụng tham số CoroutineStart.LAZY: scope.launch(start = CoroutineStart.LAZY) { ... }. Sau đó gọi job.start() hoặc job.join() để thực thi thực tế. Điều này hữu ích cho khởi tạo trễ và thực thi coroutine có điều kiện.

Tổng kết

  • Coroutine Builder — hàm tạo coroutine xác định cách thực thi và kiểu trả về của nó
  • launch — trình xây dựng chính cho các tác vụ không có kết quả, trả về Job để quản lý coroutine
  • async — trình xây dựng cho tính toán song song, trả về Deferred với khả năng await() kết quả
  • runBlocking — trình xây dựng chặn cho main() và kiểm thử, không khuyến khích trên luồng chính Android
  • Đồng thời có cấu trúc đảm bảo hủy tự động các coroutine con khi hủy phạm vi
  • produce không được khuyến khích — sử dụng Flow, SharedFlow hoặc StateFlow cho luồng dữ liệu phản ứng
  • Việc chọn trình xây dựng phụ thuộc vào kịch bản: fire-and-forget → launch, dữ liệu song song → async, cầu nối → runBlocking

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm