Giới thiệu Coroutines
Coroutines là gì?
Phần tiêu đề “Coroutines là gì?”Coroutines là cách Kotlin xử lý lập trình bất đồng bộ (asynchronous programming). Chúng cho phép bạn viết code “trông như” đồng bộ nhưng thực sự chạy bất đồng bộ mà không block thread.
Vấn đề: Tại sao cần bất đồng bộ?
Phần tiêu đề “Vấn đề: Tại sao cần bất đồng bộ?”Khi app Android gọi API hoặc đọc file:
// ❌ SAI: Block UI thread -> App bị đơ (ANR)fun loadData() { val data = networkCall() // Mất 3 giây updateUI(data) // User không thể tương tác trong 3 giây!}Android có quy tắc: UI thread (Main thread) không được làm việc nặng (network, database, file I/O).
Giải pháp cũ: Callbacks
Phần tiêu đề “Giải pháp cũ: Callbacks”// Callback hell - Code khó đọc, khó maintainapi.getUser(userId) { user -> api.getPosts(user.id) { posts -> api.getComments(posts[0].id) { comments -> // Nested callbacks... updateUI(user, posts, comments) } }}Giải pháp tốt hơn: Coroutines
Phần tiêu đề “Giải pháp tốt hơn: Coroutines”// ✅ Clean và dễ đọc như code đồng bộsuspend fun loadData() { val user = api.getUser(userId) // Đợi, nhưng không block! val posts = api.getPosts(user.id) // Tiếp tục sau khi user có val comments = api.getComments(posts[0].id) updateUI(user, posts, comments)}Magic: Code trông như chạy lần lượt, nhưng thực ra:
- Khi gọi
getUser(), coroutine suspend (tạm dừng) và giải phóng thread - Thread có thể làm việc khác
- Khi data về, coroutine resume (tiếp tục) từ đúng chỗ dừng
Coroutines vs Threads
Phần tiêu đề “Coroutines vs Threads”| Coroutines | Threads | |
|---|---|---|
| Tạo mới | Rất nhẹ (vài KB) | Nặng (~1-2 MB) |
| Số lượng | Hàng triệu | Vài nghìn |
| Quản lý | Tự động (structured concurrency) | Manual |
| Cancel | Dễ dàng | Phức tạp |
| Exception | Propagate tự động | Dễ bị nuốt |
Demo: 100,000 coroutines vs threads
Phần tiêu đề “Demo: 100,000 coroutines vs threads”// Coroutines: Hoạt động bình thường (~300ms)fun main() = runBlocking { repeat(100_000) { launch { delay(1000) print(".") } }}
// Threads: OutOfMemoryError!fun main() { repeat(100_000) { Thread { Thread.sleep(1000) print(".") }.start() }}Các khái niệm cốt lõi
Phần tiêu đề “Các khái niệm cốt lõi”1. Suspend Function
Phần tiêu đề “1. Suspend Function”Hàm có thể tạm dừng mà không block thread:
suspend fun fetchData(): Data { delay(1000) // Tạm dừng 1 giây (không block!) return Data()}2. Coroutine Builder
Phần tiêu đề “2. Coroutine Builder”Cách khởi chạy coroutine:
// launch - Fire and forgetlaunch { fetchData()}
// async - Trả về kết quảval deferred = async { fetchData()}val result = deferred.await()3. Coroutine Scope
Phần tiêu đề “3. Coroutine Scope”Phạm vi quản lý lifecycle của coroutines:
// ViewModel scope - tự cancel khi ViewModel bị clearviewModelScope.launch { // ...}
// Lifecycle scope - tự cancel khi lifecycle destroyedlifecycleScope.launch { // ...}4. Dispatcher
Phần tiêu đề “4. Dispatcher”Thread pool nơi coroutine chạy:
// Main thread (UI)Dispatchers.Main
// Background thread (I/O operations)Dispatchers.IO
// CPU-intensive workDispatchers.DefaultVí dụ thực tế: Gọi API
Phần tiêu đề “Ví dụ thực tế: Gọi API”class UserViewModel : ViewModel() {
private val _user = MutableStateFlow<User?>(null) val user: StateFlow<User?> = _user.asStateFlow()
fun loadUser(userId: Int) { // Chạy trong ViewModel scope viewModelScope.launch { try { // Chuyển sang IO thread để gọi network val result = withContext(Dispatchers.IO) { api.getUser(userId) }
// Quay về Main thread để update UI _user.value = result
} catch (e: Exception) { // Xử lý lỗi } } }}So sánh với các giải pháp khác
Phần tiêu đề “So sánh với các giải pháp khác”RxJava
Phần tiêu đề “RxJava”// RxJava - Học curve cao, boilerplate nhiềuapi.getUser(userId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ user -> updateUI(user) }, { error -> handleError(error) })Coroutines
Phần tiêu đề “Coroutines”// Coroutines - Đơn giản hơn nhiềuviewModelScope.launch { try { val user = withContext(Dispatchers.IO) { api.getUser(userId) } updateUI(user) } catch (e: Exception) { handleError(e) }}Setup Coroutines
Phần tiêu đề “Setup Coroutines”Thêm dependencies
Phần tiêu đề “Thêm dependencies”dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Cho Android}📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Khái niệm | Mô tả |
|---|---|
| Coroutine | Unit of async work, nhẹ hơn thread |
| suspend | Tạm dừng mà không block |
| launch | Khởi chạy coroutine (fire-and-forget) |
| async/await | Khởi chạy và lấy kết quả |
| Scope | Quản lý lifecycle |
| Dispatcher | Thread pool |
Lý do học Coroutines
Phần tiêu đề “Lý do học Coroutines”- Official - Được Kotlin và Google khuyến nghị
- Simple - Code dễ đọc như synchronous
- Efficient - Nhẹ, có thể chạy hàng triệu
- Structured - Tự động cancel, exception handling tốt
- Integrate - Tích hợp tốt với Android Jetpack
Tiếp theo
Phần tiêu đề “Tiếp theo”Học về Suspend Functions - nền tảng của coroutines.