Middle
Jak nakonfigurovat a používat korutiny v projektech Kotlin?
sobes.tech AI
Odpověď od AI
Pro nastavení korutin je třeba přidat odpovídající závislost do souboru build.gradle.
// build.gradle (modul aplikace)
dependencies {
//... další závislosti
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // pro JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // pro Android (pokud je potřeba Dispatchers.Main)
}
Použití korutin zahrnuje:
-
Rozsah života (Scope): Určuje oblast, ve které se korutiny budou vykonávat a spravovat svůj životní cyklus.
GlobalScope: Životní cyklus celé aplikace, používejte opatrně, protože může dojít ke ztrátě paměti.CoroutineScope: Vytvořen explicitně, umožňuje kontrolu zrušení korutin.- Předdefinované oblasti ve frameworkách (například
lifecycleScopev Android ViewModel).
// Příklad s CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Vytvoření Scope s Dispatcherem a Jobem fun performBackgroundTask() { myScope.launch { // Spuštění korutiny // Dlouhý výpočetní proces } } fun cancelAllTasks() { myScope.cancel() // Zrušení všech korutin v Scope } -
Tvořitelé korutin (Builders): Funkce pro spuštění korutin.
launch: Spouští korutinu, která explicitně nevrací výsledek (Job).async: Spouští korutinu, která vrací výsledek ve forměDeferred.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - builder pro strukturovanou konkurenci val data1 = async { networkCall1() } // async vrací Deferred val data2 = async { networkCall2() } // ... zpracování dat po jejich získání data1.await() // Získání výsledku z Deferred, korutina se uspí do dokončení data2.await() } suspend fun networkCall1(): String { delay(1000) // Simulace síťového požadavku return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - builder blokující aktuální vlákno (např. main nebo testy) launch { // launch vrací Job println("Fetching data...") fetchData() println("Data fetched!") } } -
Dispečery (Dispatchers): Určují, na kterém vlákně nebo vláknovém poolu bude korutina vykonávána.
Dispatchers.Default: Pro CPU-intenzivní úkoly.Dispatchers.IO: Pro blokující I/O operace (soubory, síť).Dispatchers.Main: Hlavní vlákno (pouze pro Android a Swing/JavaFX).Dispatchers.Unconfined: Spouští korutinu ve volajícím vlákně, uspí se a poté pokračuje ve vlákně, které obnovilo její běh.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Určení dispečera // Provádění I/O operace 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) // Uspání println("Unconfined thread 2: ${Thread.currentThread().name}") // Obnovení na jiném vlákně (možné) } delay(200) // Čekání na dokončení korutin } -
Funkce pozastavení (Suspending functions): Funkce označené klíčovým slovem
suspend, které mohou být pozastaveny a obnoveny bez blokování vlákna. Mohou být volány pouze z jiných pozastavitelných funkcí nebo z bloku korutiny. -
Zpracování zrušení a výjimek: Korutiny podporují strukturované zrušení a šíření výjimek.
- Zrušení:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // suspend funkce, která respektuje zrušení } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Čekání job.cancelAndJoin() // Zrušení a čekání na dokončení } - Výjimky: V případě
launchnezachycená výjimka povede k pádu aplikace (výchozí v Androidu). V případěasyncbude výjimka vyhozena při voláníawait(). Pro jemnější kontrolu lze použítCoroutineExceptionHandlerneboSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Použití zpracovatele výjimek throw IllegalStateException("Something went wrong") } job.join() // Čekání na dokončení } - Zrušení: