Giới thiệu Kotlin Coroutines
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ộ?
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
// Callback hell - Code khó đọc, khó maintain
api.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
// ✅ 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
| 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
// 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
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
Cách khởi chạy coroutine:
// launch - Fire and forget
launch {
fetchData()
}
// async - Trả về kết quả
val deferred = async {
fetchData()
}
val result = deferred.await()3. Coroutine Scope
Phạm vi quản lý lifecycle của coroutines:
// ViewModel scope - tự cancel khi ViewModel bị clear
viewModelScope.launch {
// ...
}
// Lifecycle scope - tự cancel khi lifecycle destroyed
lifecycleScope.launch {
// ...
}4. Dispatcher
Thread pool nơi coroutine chạy:
// Main thread (UI)
Dispatchers.Main
// Background thread (I/O operations)
Dispatchers.IO
// CPU-intensive work
Dispatchers.DefaultVí 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
RxJava
// RxJava - Học curve cao, boilerplate nhiều
api.getUser(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ user ->
updateUI(user)
}, { error ->
handleError(error)
})Coroutines
// Coroutines - Đơn giản hơn nhiều
viewModelScope.launch {
try {
val user = withContext(Dispatchers.IO) { api.getUser(userId) }
updateUI(user)
} catch (e: Exception) {
handleError(e)
}
}Setup Coroutines
Thêm dependencies
// build.gradle.kts
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
| 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
- 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
Học về Suspend Functions - nền tảng của coroutines.
Last updated on