Sobes.tech
Middle

Koje mogućnosti pruža Kotlin za rad sa asinhronim operacijama?

sobes.tech АИ

Одговор од АИ

Kotlin pruža korutine (coroutines) za pojednostavljenje asinhronih operacija, nudeći lagane tokove koji ne blokiraju glavni tok izvršavanja.

Ključne mogućnosti:

  • Funkcije za suspendovanje: Funkcije sa ključnom rečju suspend, koje mogu biti suspendovane i nastavljene. One ne blokiraju nit u kojoj se izvršavaju.
    suspend fun fetchData(): String {
        delay(1000) // Imitešemo dugu operaciju
        return "Podaci primljeni"
    }
    
  • Graditelji korutina: Funkcije koje se koriste za pokretanje korutina:
    • launch: Pokreće novu korutinu i vraća Job (ne blokira).
      GlobalScope.launch {
          println("Korutina pokrenuta")
      }
      
    • async: Pokreće novu korutinu i vraća Deferred<T> (blokira pri pozivu .await()).
      val deferred = GlobalScope.async {
          fetchData()
      }
      // ...
      val result = deferred.await() // Čekamo rezultat
      
    • runBlocking: Blokira trenutni tok dok se korutina ne završi (koristi se uglavnom kao most između blokirajućeg i neblokirajućeg koda, na primer u testovima).
      runBlocking {
          val data = fetchData()
          println(data)
      }
      
  • CoroutineContext: Skup elemenata koji definišu ponašanje korutine, uključujući Dispatcher i Job.
    • Dispatcher: Određuje nit ili bazen niti gde se izvršava korutina.
  • Dispatchers: Ugrađeni objekti za upravljanje nitima:
    • Dispatchers.Default: Opšti bazen pozadinskih niti.
    • Dispatchers.IO: Optimizovano za ulaz/izlaz (diskovne, mrežne operacije).
    • Dispatchers.Main: Glavni UI tok (za Android, JavaFX itd.).
    • Dispatchers.Unconfined: Pokreće korutinu u trenutnoj niti, ali nakon suspendovanja može da se nastavi u bilo kojoj niti.
    GlobalScope.launch(Dispatchers.IO) {
        // Izvršava se u ulazno/izlaznoj niti
    }
    
  • Strukturirana konkurencija: Princip prema kojem korutine imaju roditelja (CoroutineScope) i automatski se otkazuju kada se otkaže roditelj. Sprečava curenje resursa i olakšava upravljanje životnim ciklusom.
    // CoroutineScope automatski upravlja decom korutinama
    val scope = CoroutineScope(Dispatchers.Default)
    val job = scope.launch {
        // ...
    }
    // Kada se otkaže scope, otkazuju se sve dečje korutine
    scope.cancel()
    
  • Kanali: Kanali za sigurnu razmenu podataka između korutina. Mogu biti:
    • Unbuffered: Prijem se vrši tek nakon slanja.
    • Buffered: Omogućava slanje više elemenata pre blokiranja.
    • Conflated: Čuva samo poslednji poslati element.
    val channel = Channel<Int>()
    
    scope.launch {
        for (x in 1..5) channel.send(x)
        channel.close()
    }
    
    scope.launch {
        for (y in channel) println(y)
    }
    
  • Flow: Tok podataka koji može emitovati više vrednosti asinhrono. Slično RxJava Observable, ali je lakši i integrisan sa korutinama.
    fun simpleFlow(): Flow<Int> = flow {
        for (i in 1..3) {
            delay(100)
            emit(i) // Slanje vrednosti
        }
    }
    
    runBlocking {
        simpleFlow().collect { value -> println(value) } // Potrošnja vrednosti
    }
    

Ove mogućnosti omogućavaju pisanje asinhronog koda u imperativnom stilu, čineći ga čitljivijim i održivijim u poređenju sa korišćenjem callback-ova ili Future.