Middle
Ako nakonfigurovať a používať korutiny v projektoch Kotlin?
sobes.tech AI
Odpoveď od AI
Na nastavenie korutín je potrebné pridať príslušnú závislosť do súboru build.gradle.
// build.gradle (modul aplikácie)
dependencies {
//... ďalšie závislosti
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // pre JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // pre Android (ak je potrebný Dispatchers.Main)
}
Použitie korutín zahŕňa:
-
Rozsah života (Scope): Určuje oblasť, v ktorej sa korutiny budú vykonávať a spravovať svoj životný cyklus.
GlobalScope: Oblasť života celej aplikácie, používajte opatrne, pretože môže dôjsť ku úniku pamäte.CoroutineScope: Vytvára sa explicitne, umožňuje kontrolu nad zrušením korutín.- Preddefinované oblasti vo frameworkoch (napríklad
lifecycleScopev Android ViewModel).
// Príklad s CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Vytvorenie Scope s Dispatcherom a Jobom fun performBackgroundTask() { myScope.launch { // Spustenie korutiny // Dlhý výpočtový proces } } fun cancelAllTasks() { myScope.cancel() // Zrušenie všetkých korutín v Scope } -
Tvorcovia korutín (Builders): Funkcie na spustenie korutín.
launch: Spúšťa korutinu, ktorá nevracia výsledok explicitne (Job).async: Spúšťa korutinu, ktorá vracia výsledok vo formeDeferred.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - builder pre štruktúrovanú konkurenciu val data1 = async { networkCall1() } // async vracia Deferred val data2 = async { networkCall2() } // ... spracovanie dát po ich získaní data1.await() // Získanie výsledku z Deferred, korutina sa uspí do dokončenia data2.await() } suspend fun networkCall1(): String { delay(1000) // Imitačný sieťový požiadavok return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - builder na blokovanie aktuálneho vlákna (napr. main alebo testy) launch { // launch vracia Job println("Fetching data...") fetchData() println("Data fetched!") } } -
Dispečery (Dispatchers): Určujú, na ktorom vlákne alebo vláknovom poole bude korutina vykonávaná.
Dispatchers.Default: Pre CPU-intenzívne úlohy.Dispatchers.IO: Pre blokujúce I/O operácie (súbory, sieť).Dispatchers.Main: Hlavné vlákno (len pre Android a Swing/JavaFX).Dispatchers.Unconfined: Spúšťa korutinu v volajúcom vlákne, uspí sa a potom pokračuje vo vlákne, ktoré ju obnovilo.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Určenie dispečera // Vykonanie I/O operácie 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) // Uspanie println("Unconfined thread 2: ${Thread.currentThread().name}") // Obnovenie v inom vlákne (možno) } delay(200) // Čakanie na dokončenie korutín } -
Funkcie na pozastavenie (Suspending functions): Funkcie označené kľúčovým slovom
suspend, ktoré môžu byť pozastavené a obnovené bez blokovania vlákna. Môžu byť volané iba z iných pozastaviteľných funkcií alebo z bloku korutiny. -
Spracovanie zrušenia a výnimiek: Korutiny podporujú štruktúrované zrušenie a šírenie výnimiek.
- Zrušenie:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // suspend funkcia, ktorá rešpektuje zrušenie } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Čakanie job.cancelAndJoin() // Zrušenie a čakanie na dokončenie } - Výnimky: V prípade
launch, nezachytené výnimky povedú k pádu aplikácie (predvolene v Android). V prípadeasync, výnimka bude vyhodená pri volaníawait(). Pre jemnejšiu kontrolu sa používajúCoroutineExceptionHandleraleboSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Použitie spracovateľa výnimiek throw IllegalStateException("Something went wrong") } job.join() // Čakanie na dokončenie } - Zrušenie: