Sobes.tech
Middle

Kokias galimybes siūlo Kotlin dirbti su asinchroninėmis operacijomis?

sobes.tech AI

Atsakymas iš AI

Kotlin siūlo korutinas (coroutines) asinchroninėms operacijoms supaprastinti, siūlydama lengvus srautus, kurie neblokuoja pagrindinio vykdymo srauto.

Pagrindinės galimybės:

  • Suspension Functions: funkcijos su suspend raktiniu žodžiu, kurios gali būti sustabdytos ir atnaujintos. Jos neblokuoja vykdymo srauto.
    suspend fun fetchData(): String {
        delay(1000) // Imituojame ilgą operaciją
        return "Duomenys gauti"
    }
    
  • Coroutines Builders: funkcijos, naudojamos korutinų paleidimui:
    • launch: paleidžia naują korutiną ir grąžina Job (neblokuojantis).
      GlobalScope.launch {
          println("Korutina paleista")
      }
      
    • async: paleidžia naują korutiną ir grąžina Deferred<T> (blokuoja .await() iškvietimo metu).
      val deferred = GlobalScope.async {
          fetchData()
      }
      // ...
      val result = deferred.await() // Laukiame rezultato
      
    • runBlocking: blokuoja esamą srautą iki korutinų pabaigos (pagrindinis naudojimas kaip tiltas tarp blokuojančio ir neblokuojančio kodo, pvz., testuose).
      runBlocking {
          val data = fetchData()
          println(data)
      }
      
  • CoroutineContext: elementų rinkinys, apibrėžiantis korutinų elgseną, įskaitant Dispatcher ir Job.
    • Dispatcher: nustato srautą arba srautų baseiną, kuriame vykdoma korutina.
  • Dispatchers: įmontuoti objektai srautų valdymui:
    • Dispatchers.Default: bendras foninių srautų baseinas.
    • Dispatchers.IO: optimizuotas įvesties/išvesties operacijoms (diske, tinkle).
    • Dispatchers.Main: pagrindinis UI srautas (Android, JavaFX ir kt.).
    • Dispatchers.Unconfined: paleidžia korutiną esamame sraute, bet po sustabdymo gali būti atnaujinta bet kuriame sraute.
    GlobalScope.launch(Dispatchers.IO) {
        // vykdoma įvesties/išvesties sraute
    }
    
  • Structured Concurrency: principas, pagal kurį korutinoms yra tėvas (CoroutineScope) ir jos automatiškai atšaukiamos, kai atšaukiamas tėvas. Tai padeda išvengti išteklių nutekėjimo ir supaprastina gyvavimo ciklo valdymą.
    // CoroutineScope automatiškai valdo vaikų korutinas
    val scope = CoroutineScope(Dispatchers.Default)
    val job = scope.launch {
        // ...
    }
    // Atšaukus scope, atšaukiamos visos vaikų korutinos
    scope.cancel()
    
  • Channels: kanalai saugiam duomenų perdavimui tarp korutinų. Gali būti:
    • Unbuffered: priėmimas vyksta tik po siuntimo.
    • Buffered: leidžia siųsti kelis elementus prieš blokuojant.
    • Conflated: saugo tik paskutinį siųstą 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: duomenų srautas, kuris gali išleisti kelis reikšmes asinchroniškai. Panašus į RxJava Observable, bet lengvesnis ir integruotas su korutinomis.
    fun simpleFlow(): Flow<Int> = flow {
        for (i in 1..3) {
            delay(100)
            emit(i) // reikšmės siuntimas
        }
    }
    
    runBlocking {
        simpleFlow().collect { value -> println(value) } // reikšmių suvartojimas
    }
    

Šios galimybės leidžia rašyti asinchroninį kodą imperatyviu stiliumi, padaro jį lengviau skaitomą ir prižiūrimą nei naudojant kolbekus ar Future.