Coroutine Builder — Kotlin Coroutines függvények, amelyek korutinokat hoznak létre és indítanak el, meghatározva azok végrehajtási módját. A launch, async, runBlocking és produce builderek különböző forgatókönyveket fednek le: a háttérfeladatoktól az eredményt visszaadó párhuzamos számításokig. A JetBrains, 2024 adatai szerint a Coroutine Builder a korutinmodell alapja, biztosítva a strukturált konkurenciát és az életciklus-kezelést.
Főbb pontok
Coroutine Builder — egy Kotlin kiterjesztési függvény, amely elfogadja a CoroutineScope-ot és egy suspend-blokkot, létrehozva és elindítva egy új korutint. Minden builder meghatározza, hogy a korutin hogyan lesz végrehajtva: eredménnyel vagy anélkül, a szál blokkolásával vagy aszinkron módon. A builderek belépési pontok a nyelv korutinmodelljébe.
Minden builder a CoroutineScope-on keresztül működik, amely kezeli a gyermek korutinok életciklusát. A scope törlésekor az összes rajta keresztül elindított korutin automatikusan törlődik — ez a strukturált konkurencia elve. Ez a megközelítés megakadályozza a korutin szivárgását és garantálja a kiszámítható befejezést.
import kotlinx.coroutines.*
fun main() = runBlocking {
// A builderek a CoroutineScope-on belül működnek
val job = launch {
delay(1000L)
println("Világ!")
}
println("Helló,")
job.join()
}
A Kotlin négy beépített korutin buildert biztosít: launch, async, runBlocking és produce. Mindegyiknek saját visszatérési típusa és alkalmazási területe van. Az Android mobilfejlesztéshez a fő builderek a launch és az async — nem blokkoló módon működnek, és integrálódnak az architektúra komponensekkel.
| Builder | Visszatérési típus | Szál blokkolása | Forgatókönyv |
|---|---|---|---|
| launch | Job | Nem | Fire-and-forget feladatok |
| async | Deferred<T> | Nem | Párhuzamos számítások |
| runBlocking | T | Igen | Tesztek, main függvény |
| produce | ReceiveChannel<E> | Nem | Streamelt átvitel (deprecated) |
Minden builder további paramétereket fogad: CoroutineStart (indítási stratégia), CoroutineContext (dispatcher, kivételek) és egy elnevezett kódblokk. Alapértelmezés szerint a korutin azonnal elindul (CoroutineStart.DEFAULT).
launch — a leggyakrabban használt builder Android-fejlesztésben. Elindít egy korutint, amely nem ad vissza eredményt, és visszaad egy Job objektumot az életciklus kezeléséhez. Ez az ideális választás olyan műveletekhez, ahol csak mellékhatás szükséges: mentés adatbázisba, analitika küldése, UI frissítése.
A launch builder elfogadja a CoroutineScope-ot, opcionális CoroutineContext-et és egy suspend-blokkot. A visszaadott Job lehetővé teszi a korutin törlését, befejezésére való várakozást vagy az állapot ellenőrzését.
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val job: Job = scope.launch(CoroutineStart.LAZY) {
val data = fetchFromNetwork()
saveToDatabase(data)
}
job.start()
job.join()
A CoroutineStart.LAZY paraméter késlelteti az indítást a start() vagy join() explicit meghívásáig. Ez hasznos késleltetett inicializáláshoz és feltételes indításhoz. A szabványos azonnali indításhoz a CoroutineStart.DEFAULT használatos, vagy a paraméter elhagyható.
async — builder, amely Deferred<T> ad vissza — az eredmény aszinkron ígérete. Az await() hívás felfüggeszti a korutint az eredmény eléréséig, anélkül hogy blokkolná a szálat. Ez az alapvető mechanizmus a párhuzamos feladatokhoz a Kotlin korutinokban.
Az async különösen hatékony, ha több független műveletet kell egyidejűleg végrehajtani. A suspend függvények szekvenciális hívásával ellentétben az async párhuzamosan indítja el a korutinokat, csökkentve a teljes végrehajtási időt.
suspend fun fetchUserData(): UserData {
val deferred1 = CoroutineScope(Dispatchers.IO).async { api.getProfile() }
val deferred2 = CoroutineScope(Dispatchers.IO).async { api.getSettings() }
val deferred3 = CoroutineScope(Dispatchers.IO).async { api.getNotifications() }
return UserData(
profile = deferred1.await(),
settings = deferred2.await(),
notifications = deferred3.await()
)
}
A Deferred a Job-ból származik, így az async támogatja az életciklus összes műveletét: törlés, befejezésre várakozás, kivételek kezelése. A scope törlésekor a gyermek Deferred korutinok automatikusan törlődnek.
runBlocking — az egyetlen builder, amely blokkolja az aktuális szálat a korutin befejezéséig. Létrehoz egy új CoroutineScope-ot, és elindítja a megadott korutint, blokkolva a hívó szálat. A main() belépési pontokban, tesztekben és blocking kóddal való integrációban használatos.
A runBlocking három forgatókönyvben indokolt: az alkalmazás belépési pontja (main), a suspend függvények egységtesztjei és a callback-alapú könyvtárakkal való integráció, ahol a suspend nem használható. Android production kódban a runBlocking használata a fő szálon határozottan nem ajánlott.
class CoroutineTest {
@Test
fun `test suspend function`() = runBlocking {
val result = mySuspendFunction()
assertEquals("expected", result)
}
}
Tesztekhez a runBlocking helyett a kotlinx-coroutines-test használata ajánlott TestCoroutineDispatcher-rel — ez időbeli ellenőrzést biztosít, és elkerüli a blokkolásokat a tesztkörnyezetben.
A Coroutine Builder kiválasztása a visszaadott eredménytől és a végrehajtási forgatókönyvtől függ. Ha a művelet nem igényel adatvisszaadást — használja a launch-ot. Ha az aszinkron művelet eredménye szükséges — async. A runBlocking-et csak bridginghez alkalmazza, a produce-t pedig cserélje Flow-ra a reaktív streamekhez.
Az Android projektekben Kotlin Coroutines használatával a fő builder pár a launch és az async. A launch a ViewModel-ben és UseCases-ben használatos korutinok indításához, az async pedig párhuzamos hálózati vagy adatbázis-kérésekhez. A modern könyvtárak (Ktor, Room) már támogatják a suspend függvényeket, ami minimalizálja az async közvetlen használatának szükségességét.
Gyakran Ismételt Kérdések
A launch Job-ot ad vissza, és nem adja vissza a végrehajtás eredményét, míg az async Deferred<T> ad vissza — egy objektumot, amelyből az await() segítségével lehet eredményt kapni. A launch fire-and-forget műveletekhez, az async pedig adatokat visszaadó feladatokhoz használatos.
Nem ajánlott. A runBlocking a fő szálon ANR-t okoz, és blokkolja a UI-t. Használja a lifecycleScope.launch-ot Activity és Fragment belsejében — ez beépített megoldás blokkolás nélkül.
A launch builder egy Job objektumot ad vissza, amely lehetővé teszi a korutin életciklusának vezérlését: törlés (cancel), befejezésre várakozás (join), állapot ellenőrzése (isActive, isCompleted, isCancelled).
A Deferred<T> — az async builder által visszaadott aszinkron eredményígérete. A Job-ból származik, és hozzáadja az await() metódust az eredmény eléréséhez, a getCompleted() metódust a nem blokkoló hozzáféréshez, és a getCompletionExceptionOrNull() metódust a kivétel ellenőrzéséhez.
Használja a CoroutineStart.LAZY paramétert: scope.launch(start = CoroutineStart.LAZY) { ... }. Ezután hívja meg a job.start()-ot vagy job.join()-ot a tényleges indításhoz. Ez hasznos késleltetett inicializáláshoz és a korutinok feltételes végrehajtásához.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is