CodeBlanks Logo Icon CodeBlanks

Coroutines

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

Main.kt
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

Main.kt
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

Soru
class UserRepo {
    ____ fun save(u: User) { UsersTable.insert(u) }
}
Cevap
class UserRepo {
    suspend fun save(u: User) { UsersTable.insert(u) }
}

Açıklama: suspend fun save bir coroutine içinde çağrılır.

İleri seviye bölümündeki tüm dersler