launch — Coroutine Builder v Kotlin, který spouští korutinu bez vrácení výsledku a vrací objekt Job pro řízení provádění. Tento builder implementuje vzor fire-and-forget: korutina začíná pracovat na vlákně na pozadí a automaticky končí. Podle dokumentace JetBrains, 2024, je launch hlavním způsobem spouštění paralelních úloh v Kotlin Coroutines.
Hlavní body
launch — je rozšiřující funkce Kotlin, dostupná přes import kotlinx.coroutines, která vytváří novou korutinu v daném CoroutineScope. Na rozdíl od běžných funkcí se kód uvnitř launch provádí souběžně — korutina se může pozastavit (suspend) bez blokování vlákna a později pokračovat.
Launch builder je základním stavebním blokem modelu korutin Kotlin. Nevrací vypočítanou hodnotu, ale vrací objekt Job, který umožňuje řídit provádění korutiny. Všechny podřízené korutiny spuštěné pomocí launch uvnitř jiné korutiny jsou vázány na rodičovskou.
Launch builder je definován jako inline funkce s několika parametry: CoroutineScope, CoroutineContext, CoroutineStart a suspend-blok. Parametry mají výchozí hodnoty, což činí launch pohodlným pro typické scénáře.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
Parametr context přijímá CoroutineContext, který kombinuje dispečera, obsluhu výjimek a pojmenovaný prvek. Nejčastěji se předává Dispatchers.IO, Dispatchers.Main nebo SupervisorJob pro izolaci chyb.
Job — vrácený objekt představující životní cyklus korutiny. Job může být ve stavech: New, Active, Completing, Completed, Cancelling, Cancelled. Každý stav odráží stav provádění a umožňuje reagovat na změny.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Pokrok: $i")
}
}
println("Job je aktivní: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job je zrušen: ${job.isCancelled}")
Job podporuje hierarchii: pokud je rodičovská korutina zrušena, všechny podřízené jsou automaticky zrušeny. SupervisorJob mění toto chování — podřízené korutiny nejsou zrušeny při chybě jedné z nich.
Strukturovaná konkurence znamená, že každá korutina je spuštěna v určitém CoroutineScope a scope se nedokončí, dokud všechny podřízené korutiny nedokončí svou práci. launch plně podporuje tento princip — korutiny spuštěné uvnitř jiné korutiny jsou jejími potomky.
Při vnořeném spuštění launch vzniká strom korutin. Rodičovská korutina čeká na dokončení všech potomků, což zaručuje předvídatelné pořadí provádění a zjednodušuje správu zdrojů.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Potomek 1 dokončen")
}
launch {
delay(500L)
println("Potomek 2 dokončen")
}
println("Všichni potomci dokončeni před tímto řádkem")
}
}
Toto chování se liší od konkurence založené na vláknech, kde podřízená vlákna nejsou vázána na rodičovské. V korutinách se rodič nedokončí, dokud všechny děti nedokončí svou práci.
Zpracování výjimek v launch závisí na typu Job. Pro běžný Job se výjimky šíří do rodičovské korutiny a ruší ji. Pro SupervisorJob nebo SupervisorScope jsou výjimky izolovány — chyba jedné podřízené korutiny neovlivňuje ostatní.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Zachyceno: ${e.message}")
}
}
scope.launch {
println("Toto stále běží díky SupervisorJob")
}
Pro globální zpracování nezachycených výjimek se používá CoroutineExceptionHandler. Zachycuje výjimky, které nebyly zpracovány uvnitř korutiny, a umožňuje zaznamenat chybu bez pádu aplikace.
V Android se launch používá všude: od ViewModel po WorkManager. Hlavním vzorem je použití lifecycleScope ve Fragment a viewModelScope ve ViewModel pro automatické zrušení korutin při ukončení životního cyklu komponenty.
class ProfileViewModel : ViewModel() {
private val repository = UserRepository()
fun loadProfile(userId: String) {
viewModelScope.launch(Dispatchers.IO) {
val profile = repository.fetchProfile(userId)
withContext(Dispatchers.Main) {
_profileState.update { it.copy(profile = profile) }
}
}
}
}
viewModelScope automaticky ruší korutiny při zničení ViewModel. To eliminuje úniky paměti a zaručuje, že operace na pozadí nepokračují po ztrátě kontextu. Dále lze použít withContext pro přepínání mezi dispečery.
Často kladené otázky
launch vrací Job a nevrací výsledek provádění, zatímco async vrací Deferred<T> pro získání výsledku. launch se používá pro operace fire-and-forget, async — když je třeba počkat a použít vrácenou hodnotu.
Zavolejte job.cancel() na uloženém objektu Job. Pro hromadné zrušení zrušte celý CoroutineScope pomocí scope.cancel(). Korutina musí být kooperativní — kontrolovat isActive nebo používat kontrolovatelné suspend funkce.
Použijte try-catch uvnitř bloku launch nebo předejte CoroutineExceptionHandler v CoroutineContext. Pro izolaci chyb použijte SupervisorJob — pak výjimka v jedné podřízené korutině nezruší ostatní.
Ne, launch je rozšiřující funkcí CoroutineScope. Bez scope nebude korutina moci dodržet princip strukturované konkurence. Používejte GlobalScope.launch opatrně — vytváří to korutinu bez vazby na životní cyklus.
Počet je omezen fondem vláken dispečera. Dispatchers.Default používá počet vláken rovný počtu jader CPU. Dispatchers.IO podporuje až 64 vláken. Při spouštění většího počtu korutin jsou zařazeny do fronty.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také