Hogyan állítsuk be és használjuk a korutinokat Kotlin projektekben?
sobes.tech MI
Válasz az MI-től
A korutinok beállításához megfelelő függőséget kell hozzáadni a build.gradle fájlhoz.
// build.gradle (alkalmazás modul)
dependencies {
//... egyéb függőségek
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Androidhoz (ha szükséges Dispatchers.Main)
}
A korutinok használata magában foglalja:
-
Életciklus (Scope): Meghatározza azt a területet, ahol a korutinok futnak és kezelik életciklusukat.
GlobalScope: Az alkalmazás teljes életciklusa, óvatosan használandó, mert memória szivárgáshoz vezethet.CoroutineScope: Egyértelműen létrehozva, lehetővé teszi a korutinok leállítását.- Előre definiált területek keretrendszerekben (pl.
lifecycleScopeAndroid ViewModel-ben).
// Példa CoroutineScope használatára val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Scope létrehozása Dispatcherrel és Jobbal fun performBackgroundTask() { myScope.launch { // Korutina indítása // Hosszú számítási folyamat } } fun cancelAllTasks() { myScope.cancel() // Minden korutina leállítása a Scope-ban } -
Korutin készítők (Builders): Funkciók a korutinok indítására.
launch: Indít egy korutint, amely nem ad vissza eredményt (Job-t ad vissza).async: Indít egy korutint, amely eredményt ad visszaDeferredformájában.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope a strukturált konkurencia számára val data1 = async { networkCall1() } // async Deferred-et ad vissza val data2 = async { networkCall2() } // ... adatok feldolgozása az eredmények után data1.await() // Eredmény lekérése a Deferred-ből, a korutina alvásba kerül addig, amíg nem kész data2.await() } suspend fun networkCall1(): String { delay(1000) // Hálózati kérés szimulálása return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking a blokkoló builder a jelenlegi szálon (pl. main vagy tesztek) launch { // launch Job-t ad vissza println("Fetching data...") fetchData() println("Data fetched!") } } -
Dispatcherek (Dispatchers): Meghatározzák, hogy melyik szálon vagy szálpufferben fusson a korutina.
Dispatchers.Default: CPU-intenzív feladatokhoz.Dispatchers.IO: Blokkoló I/O műveletekhez (fájl hozzáférés, hálózat).Dispatchers.Main: Fő szál (csak Android és Swing/JavaFX esetén).Dispatchers.Unconfined: A hívó szálon indítja a korutint, majd alvásba kerül, és később a folytatás szálán folytatódik.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Dispatcher megadása // I/O művelet végrehajtása 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) // Alvás println("Unconfined thread 2: ${Thread.currentThread().name}") // Folytatás más szálon (lehetséges) } delay(200) // Várakozás a korutinok befejezésére } -
Szüneteltető függvények (Suspending functions): A
suspendkulcsszóval ellátott függvények, amelyek szüneteltethetők és folytathatók anélkül, hogy blokkolnák a szálat. Csak más szüneteltető függvényekből vagy korutin blokkokból hívhatók. -
Megszakítás és kivételek kezelése: A korutinok támogatják a strukturált megszakítást és a kivételek terjesztését.
- Megszakítás:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // szüneteltető függvény, amely figyelembe veszi a megszakítást } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Várakozás job.cancelAndJoin() // Megszakítás és várakozás a befejezésre } - Kivétel: A
launchesetén a kezeletlen kivétel a program leállásához vezet (Androidon alapértelmezés szerint). Aasyncesetén a kivétel aawait()hívásakor dobódik. A finomabb kontroll érdekében használhatók aCoroutineExceptionHandlervagy aSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Kivételkezelő alkalmazása throw IllegalStateException("Something went wrong") } job.join() // Befejezés várása } - Megszakítás: