Middle
Kaip konfigūruoti ir naudoti korutinas Kotlin projektuose?
sobes.tech AI
Atsakymas iš AI
Korutinų konfigūracija reikalauja atitinkamos priklausomybės pridėjimo į build.gradle failą:
// build.gradle (modulio dalis)
dependencies {
//... kitos priklausomybės
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 (jei reikalingas Dispatchers.Main)
}
Korutinų naudojimas apima:
-
Gyvenimo ciklas (Scope): Apibrėžia, kur ir kaip vykdomos korutinės funkcijos ir kaip valdyti jų gyvavimo ciklą:
GlobalScope: Visos programos apimtimi, naudoti atsargiai, nes gali būti atminties nutekėjimas.CoroutineScope: Aiškiai sukurtas, leidžia kontroliuoti atšaukimą.- Anksčiau apibrėžti lauko (scope) pavyzdžiai (pavyzdžiui,
lifecycleScopeAndroid ViewModel).
// Pavyzdys su CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Sukuria scope su Dispatcher ir Job fun performBackgroundTask() { myScope.launch { // Korutinos paleidimas // Ilgas skaičiavimas } } fun cancelAllTasks() { myScope.cancel() // Atšaukia visas korutinas scope'e } -
Korutinų kūrėjai (Builders): Funkcijos korutinų paleidimui:
launch: Paleidžia korutiną, kuri negrąžina rezultato (grąžinaJob).async: Paleidžia korutiną, kuri grąžina rezultatąDeferred:
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - struktūrizuotos konkurencijos kūrėjas val data1 = async { networkCall1() } // async grąžina Deferred val data2 = async { networkCall2() } // Duomenų apdorojimas po jų gavimo data1.await() // Rezultato gavimas iš Deferred, sustabdo korutiną data2.await() } suspend fun networkCall1(): String { delay(1000) // Tinklo užklausos imitacija return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - blokuoja esantį srautą launch { // launch grąžina `Job` println("Fetching data...") fetchData() println("Data fetched!") } } -
Dispečeriai (Dispatchers): Nustato, kuriame sraute ar srautų grupėje bus vykdoma korutina:
Dispatchers.Default: CPU intensyviems darbamsDispatchers.IO: Blokuojančioms I/O operacijomsDispatchers.Main: Pagrindinis srautas (tik Android ir Swing/JavaFX)Dispatchers.Unconfined: Paleidžia korutiną iškvietusio srauto, vėliau atnaujina kitame sraute:
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Nustatymas dispečerio // I/O operacijos vykdymas 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) // Miego println("Unconfined thread 2: ${Thread.currentThread().name}") // Atkūrimas kitame sraute } delay(200) // Laukiama korutinų pabaigos } -
Laukiamos funkcijos (Suspending functions): Funkcijos, pažymėtos
suspend, kurios gali būti sustabdytos ir atnaujintos be srauto blokavimo: -
Atšaukimas ir išimčių apdorojimas: Korutinai palaiko struktūrizuotą atšaukimą ir išimčių plitimą:
- Atšaukimas:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // sustabdomoji funkcija, gerbianti atšaukimą } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Trumpo laiko laukimas job.cancelAndJoin() // Atšaukimas ir laukimas pabaigos } - Išimtys:
launch-e — neapdorota išimtis sukels programos žlugdymą (Android pagal numatytuosius nustatymus).async-e — išimtis bus išmestaawait()kvietimo metu. Daugiau kontrolės galima pasiekti naudojantCoroutineExceptionHandlerarbaSupervisorJob:
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Naudojant apdorotoją throw IllegalStateException("Something went wrong") } job.join() // Laukiama pabaigos } - Atšaukimas: