Coroutines
- Kotlin kursu
- İleri seviye
- Ders 82/83
- 6 dk
Coroutines ve Flow ile asenkron işleme yazarsın.
Coroutines ile suspend çağrılar
Dördüncü ders, UserRepo ve Api metotlarını suspend yapar. Bu, Ktor'ın suspend tabanlı API'sini taklit eder. main artık runBlocking ile açılır.
Örnek: suspend fun save(u: User). suspend fun find(id: Int): User?. main = runBlocking { repo.save(...); api.route(...) }. suspend fonksiyonlar bir coroutine içinde çağrılır. Bu kalıp, eşzamanlı I/O için uygundur; thread'leri bloklamaz.
runBlocking ve coroutine scope
runBlocking bir coroutine scope açar ve bloke eder. suspend fonksiyonlar bu scope içinde normal fonksiyon gibi çağrılır.
Örnek: fun main() = runBlocking { repo.save(User(1, "Ayşe")); println(api.route("/users/1")) }. runBlocking, main'in bitmesini coroutine tamamlanana dek bekletir. Bu kalıp, eşzamanlı kodu senkron test etmenin temel yoludur.
Uygulama suspend metotlara dönüştür
Mevcut tüm tanımları koru. UserRepo.save, UserRepo.find ve Api.route metotlarının başına suspend ekle. main fonksiyonunu fun main() = runBlocking { } biçimine getir; içine repo.save(User(1, "Ayşe")) ve println(api.route("/users/1")) çağrılarını taşı. import kotlinx.coroutines.runBlocking ekle.
Başlangıç kodu
data class User(val id: Int, val name: String)
object UsersTable {
val rows = mutableListOf<User>()
fun insert(u: User) { rows.add(u) }
fun select(id: Int): User? = rows.find { it.id == id }
}
class UserRepo {
fun save(u: User) { UsersTable.insert(u) }
fun find(id: Int): User? = UsersTable.select(id)
}
class Api(val repo: UserRepo) {
fun route(path: String): String {
return when {
path.startsWith("/users/") -> {
val id = path.removePrefix("/users/").toInt()
repo.find(id)?.name ?: "not found"
}
else -> "404"
}
}
}
fun main() {
val repo = UserRepo()
repo.save(User(1, "Ayşe"))
val api = Api(repo)
println(api.route("/users/1"))
}
// save, find, route metotlarını suspend yap
// main'i runBlocking ile açÖrnek çözüm
import kotlinx.coroutines.runBlocking
data class User(val id: Int, val name: String)
object UsersTable {
val rows = mutableListOf<User>()
fun insert(u: User) { rows.add(u) }
fun select(id: Int): User? = rows.find { it.id == id }
}
class UserRepo {
suspend fun save(u: User) { UsersTable.insert(u) }
suspend fun find(id: Int): User? = UsersTable.select(id)
}
class Api(val repo: UserRepo) {
suspend fun route(path: String): String {
return when {
path.startsWith("/users/") -> {
val id = path.removePrefix("/users/").toInt()
repo.find(id)?.name ?: "not found"
}
else -> "404"
}
}
}
fun main() = runBlocking {
val repo = UserRepo()
repo.save(User(1, "Ayşe"))
val api = Api(repo)
println(api.route("/users/1"))
}Beklenen çıktı
Ayşe
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 suspend fonksiyon main'de nasıl çağrılır?
- runBlocking içinde Doğru cevap
- Thread.start ile
- Timer ile
- Doğrudan
Açıklama: suspend fonksiyon runBlocking gibi bir coroutine içinde çağrılır.
2 Coroutines parçalarını eşle
| Kavram | Anlamı |
|---|---|
suspend fun |
Bekleyebilen fonksiyon |
runBlocking |
Scope açma |
repo.save(...) |
Çağrı |
main = runBlocking |
Giriş noktası |
3 suspend fonksiyon tanımını tamamla
class UserRepo {
____ fun save(u: User) { UsersTable.insert(u) }
}
class UserRepo {
suspend fun save(u: User) { UsersTable.insert(u) }
}
Açıklama: suspend fun save bir coroutine içinde çağrılır.