Sobes.tech
Middle

Ce capacități oferă Kotlin pentru a lucra cu operații asincrone?

sobes.tech AI

Răspuns de la AI

Kotlin oferă corutine pentru simplificarea operațiilor asincrone, oferind fire ușoare care nu blochează firul principal.

Funcții cheie:

  • Funcții de suspendare: Funcții cu cuvântul cheie suspend, care pot fi suspendate și reluate. Nu blochează firul în care sunt executate.
    suspend fun fetchData(): String {
        delay(1000) // Simulează o operație lungă
        return "Date primite"
    }
    
  • Constructori de corutine: Funcții folosite pentru a porni corutine:
    • launch: Pornește o nouă corutină și returnează un Job (ne-blocant).
      GlobalScope.launch {
          println("Corutină lansată")
      }
      
    • async: Pornește o nouă corutină și returnează un Deferred<T> (.await() blochează).
      val deferred = GlobalScope.async {
          fetchData()
      }
      // ...
      val result = deferred.await() // Așteaptă rezultatul
      
    • runBlocking: Blochează firul curent până când corutina se finalizează (folosit în punți între cod blocant și ne-blocant, de exemplu în teste).
      runBlocking {
          val data = fetchData()
          println(data)
      }
      
  • Contextul corutinei: Set de elemente care definesc comportamentul corutinei, inclusiv Dispatcher și Job.
    • Dispatcher: Determină firul sau grupul de fire în care rulează corutina.
  • Dispatchers: Obiecte încorporate pentru gestionarea firelor:
    • Dispatchers.Default: Pool comun de fire de fundal.
    • Dispatchers.IO: Optimizat pentru intrare/ieșire (operații pe disc, rețea).
    • Dispatchers.Main: Firul principal UI (pentru Android, JavaFX etc.).
    • Dispatchers.Unconfined: Rulează corutina în firul curent, dar poate relua în orice fir după suspendare.
    GlobalScope.launch(Dispatchers.IO) {
        // Execută în firul de intrare/ieșire
    }
    
  • Concurență structurată: Principiu conform căruia corutinele au un părinte (CoroutineScope) și sunt anulate automat la anularea părintelui. Previne scurgerile de resurse și simplifică gestionarea ciclului de viață.
    // CoroutineScope gestionează automat corutinele copil
    val scope = CoroutineScope(Dispatchers.Default)
    val job = scope.launch {
        // ...
    }
    // La anularea scope-ului, toate corutinele copil sunt anulate
    scope.cancel()
    
  • Canale: Pentru transfer sigur de date între corutine. Pot fi:
    • Fără buffer: Recepția are loc doar după trimitere.
    • Bufferate: Permite trimiterea mai multor elemente înainte de blocare.
    • Conflated: Stochează doar ultimul element trimis.
    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: Flux de date care poate emite mai multe valori asincron. Similar cu RxJava Observable, dar mai ușor și integrat cu corutine.
    fun simpleFlow(): Flow<Int> = flow {
        for (i in 1..3) {
            delay(100)
            emit(i) // Trimiterea valorii
        }
    }
    
    runBlocking {
        simpleFlow().collect { value -> println(value) } // Consumarea valorilor
    }
    

Aceste funcții permit scrierea de cod asincron în stil imperativ, făcându-l mai ușor de citit și întreținut comparativ cu utilizarea callback-urilor sau Future.