Sobes.tech
Middle

Kā konfigurēt un izmantot korutinas Kotlin projektos?

sobes.tech AI

Atbilde no AI

Korutīnu konfigurācija prasa atbilstošu atkarību pievienošanu build.gradle failam:

// build.gradle (moduļa daļa)
dependencies {
    //... citas atkarības
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // JVM, Android, JS, Native
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Android (ja nepieciešams Dispatchers.Main)
}

Korutīnu izmantošana ietver:

  1. Dzīves cikls (Scope): Nosaka, kur un kā tiks izpildītas korutīnas un kā kontrolēt to dzīves ciklu:

    • GlobalScope: Visai lietojumprogrammai, lietot uzmanīgi, jo ir iespējama atmiņas noplūde.
    • CoroutineScope: Skaidri izveidots, ļauj pārtraukt korutīnas.
    • Iepriekš definēti fāžu (scope) piemēri (piemēram, lifecycleScope Android ViewModel).
    // Piemērs ar CoroutineScope
    val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Izveido Scope ar Dispatcher un Job
    
    fun performBackgroundTask() {
        myScope.launch { // Korutīnas uzsākšana
            // Ilgstošs skaitļošanas process
        }
    }
    
    fun cancelAllTasks() {
        myScope.cancel() // Atceļ visas korutīnas Scope
    }
    
  2. Korutīnu būvētāji (Builders): Funkcijas korutīnu uzsākšanai:

    • launch: Uzsāk korutīnu, kas neatgriež rezultātu (atgriež Job).
    • async: Uzsāk korutīnu, kas atgriež rezultātu Deferred:
    import kotlinx.coroutines.*
    
    suspend fun fetchData() = coroutineScope { // coroutineScope - strukturētas konkurētspējas būvētājs
        val data1 = async { networkCall1() } // async atgriež Deferred
        val data2 = async { networkCall2() }
    
        // Datu apstrāde pēc to saņemšanas
        data1.await() // Rezultāta saņemšana no Deferred, bloķējot korutīnu
        data2.await()
    }
    
    suspend fun networkCall1(): String {
        delay(1000) // Tīkla pieprasījuma imitācija
        return "Data 1"
    }
    
    suspend fun networkCall2(): String {
        delay(1500)
        return "Data 2"
    }
    
    fun startFetching() = runBlocking { // runBlocking - bloķē esošo plūsmu
        launch { // launch atgriež `Job`
            println("Fetching data...")
            fetchData()
            println("Data fetched!")
        }
    }
    
  3. Dispečeri (Dispatchers): Nosaka, kurā plūsmā vai plūsmu grupā tiks izpildīta korutīna:

    • Dispatchers.Default: CPU-intensīviem uzdevumiem
    • Dispatchers.IO: Bloķējošām I/O operācijām
    • Dispatchers.Main: Galvenā plūsma (tikai Android un Swing/JavaFX)
    • Dispatchers.Unconfined: Sākas izsaucējošajā plūsmā, pēc tam atsāk citā plūsmā:
    import kotlinx.coroutines.*
    
    fun simpleTask() {
        GlobalScope.launch(Dispatchers.IO) { // Dispečera norādīšana
            // I/O operācijas izpilde
            println("Running on thread: ${Thread.currentThread().name}")
        }
    }
    
    fun main() = runBlocking {
        launch(Dispatchers.Default) {
            println("Default thread: ${Thread.currentThread().name}")
        }
        launch(Dispatchers.Unconfined) {
             println("Unconfined thread 1: ${Thread.currentThread().name}")
             delay(100) // Miegs
             println("Unconfined thread 2: ${Thread.currentThread().name}") // Atsāk citā plūsmā
        }
        delay(200) // Gaidīšana korutīnu pabeigšanai
    }
    
  4. Gaidošās funkcijas (Suspending functions): Funkcijas, kas marķētas ar suspend, kuras var tikt pārtrauktas un atsāktas bez plūsmas bloķēšanas:

  5. Atcelšana un izņēmumu apstrāde: Korutīnas atbalsta strukturētu atcelšanu un izņēmumu izplatīšanu:

    • Atcelšana:
      import kotlinx.coroutines.*
      
      fun cancellableTask() = GlobalScope.launch {
          try {
              repeat(1000) { i ->
                  println("Working $i ...")
                  delay(100) // pārtraukšanas funkcija, kas ievēro atcelšanu
              }
          } catch (e: CancellationException) {
              println("Task was cancelled!")
          } finally {
              println("Cleaning up...")
          }
      }
      
      fun main() = runBlocking {
          val job = cancellableTask()
          delay(500) // Gaidīt mazliet
          job.cancelAndJoin() // Atcelt un gaidīt pabeigšanu
      }
      
    • Izņēmumi: launch-ā — neapstrādāta izņēmuma izraisīs lietojumprogrammas krišanu (Android pēc noklusējuma). async-ā — izņēmums tiks izsviests, kad tiks izsaukts await(). Plašāka kontrole ir ar CoroutineExceptionHandler vai SupervisorJob:
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        val handler = CoroutineExceptionHandler { _, exception ->
            println("Caught exception: $exception")
        }
    
        val job = GlobalScope.launch(handler) { // Ar apstrādātāju
            throw IllegalStateException("Something went wrong")
        }
        job.join() // Gaidīt pabeigšanu
    }