Sobes.tech
Middle

Kotlin projelerinde korutinleri nasıl yapılandırıp kullanılır?

sobes.tech yapay zeka

AI'dan gelen yanıt

Coroutinleri yapılandırmak için, ilgili bağımlılığı build.gradle dosyasına eklemeniz gerekir.

// build.gradle (app modülü)
dependencies {
    //... diğer bağımlılıklar
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // JVM, Android, JS, Native için
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Android için (eğer Dispatchers.Main gerekiyorsa)
}

Coroutin kullanımı şunları içerir:

  1. Kapsam (Scope): Coroutinlerin çalışacağı alanı tanımlar ve yaşam döngüsünü yönetir.

    • GlobalScope: Tüm uygulama alanı, dikkatli kullanın, çünkü bellek sızıntılarına neden olabilir.
    • CoroutineScope: Açıkça oluşturulur, coroutinlerin iptalini kontrol etmeye olanak tanır.
    • Çerçeve tarafından önceden tanımlanmış alanlar (örneğin, Android ViewModel'deki lifecycleScope).
    // CoroutineScope ile örnek
    val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Dispatcher ve Job ile Scope oluşturma
    
    fun performBackgroundTask() {
        myScope.launch { // Coroutin başlat
            // Uzun süren hesaplama işlemi
        }
    }
    
    fun cancelAllTasks() {
        myScope.cancel() // Scope içindeki tüm coroutinleri iptal et
    }
    
  2. İnşa Ediciler (Builders): Coroutinleri başlatmak için fonksiyonlar.

    • launch: Sonucu açıkça döndürmeyen coroutin başlatır (Job döner).
    • async: Sonucu Deferred olarak döndüren coroutin başlatır.
    import kotlinx.coroutines.*
    
    suspend fun fetchData() = coroutineScope { // coroutineScope - yapılandırılmış eşzamanlılık için builder
        val data1 = async { networkCall1() } // async bir Deferred döner
        val data2 = async { networkCall2() }
    
        // ... verilerin alınmasından sonra işleme
        data1.await() // Deferred'den sonucu alır, coroutin suspend olur
        data2.await()
    }
    
    suspend fun networkCall1(): String {
        delay(1000) // Ağ isteği simülasyonu
        return "Data 1"
    }
    
    suspend fun networkCall2(): String {
        delay(1500)
        return "Data 2"
    }
    
    fun startFetching() = runBlocking { // runBlocking - ana veya testler için thread'i bloklar
        launch { // launch bir Job döner
            println("Veriler alınıyor...")
            fetchData()
            println("Veriler alındı!")
        }
    }
    
  3. Dağıtıcılar (Dispatchers): Coroutinlerin hangi thread veya thread havuzunda çalışacağını belirler.

    • Dispatchers.Default: CPU yoğun görevler için.
    • Dispatchers.IO: Bloklayan I/O işlemleri için (dosya erişimi, ağ).
    • Dispatchers.Main: Ana thread (sadece Android ve Swing/JavaFX için).
    • Dispatchers.Unconfined: Coroutin'i çağıran thread'de başlatır, askıya alır ve sonra onu yeniden başlatan thread'de devam eder.
    import kotlinx.coroutines.*
    
    fun simpleTask() {
        GlobalScope.launch(Dispatchers.IO) { // Dispatcher belirleme
            // I/O işlemini gerçekleştir
            println("Thread üzerinde çalışıyor: ${Thread.currentThread().name}")
        }
    }
    
    fun main() = runBlocking {
        launch(Dispatchers.Default) {
            println("Varsayılan thread: ${Thread.currentThread().name}")
        }
        launch(Dispatchers.Unconfined) {
             println("Unconfined thread 1: ${Thread.currentThread().name}")
             delay(100) // Askıya alma
             println("Unconfined thread 2: ${Thread.currentThread().name}") // Farklı bir thread'de devam edebilir
        }
        delay(200) // Coroutinlerin tamamlanmasını bekle
    }
    
  4. Askıya alınabilen fonksiyonlar (Suspending functions): suspend anahtar kelimesiyle işaretlenmiş fonksiyonlar, thread'i bloklamadan askıya alınabilir ve devam edebilir. Sadece diğer askıya alınabilen fonksiyonlardan veya coroutine bloklarından çağrılabilir.

  5. İptal ve istisna işleme: Coroutinler yapılandırılmış iptal ve istisna yayılımını destekler.

    • İptal:
      import kotlinx.coroutines.*
      
      fun cancellableTask() = GlobalScope.launch {
          try {
              repeat(1000) { i ->
                  println("Çalışıyor $i ...")
                  delay(100) // askıya alma fonksiyonu, iptali dikkate alır
              }
          } catch (e: CancellationException) {
              println("İş iptal edildi!")
          } finally {
              println("Temizleniyor...")
          }
      }
      
      fun main() = runBlocking {
          val job = cancellableTask()
          delay(500) // Biraz bekle
          job.cancelAndJoin() // İptal et ve bitişini bekle
      }
      
    • İstisnalar: launch durumunda, yakalanmayan istisna uygulamanın çökmesine neden olur (Android'de varsayılan). async durumunda, istisna await() çağrıldığında fırlatılır. Daha ince kontrol için CoroutineExceptionHandler veya SupervisorJob kullanılır.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        val handler = CoroutineExceptionHandler { _, exception ->
            println("Yakalanan istisna: $exception")
        }
    
        val job = GlobalScope.launch(handler) { // İşleyici uygulama
            throw IllegalStateException("Bir şeyler yanlış gitti")
        }
        job.join() // Bitişini bekle
    }