launch — Coroutine Builder în Kotlin care lansează o corutină fără a returna un rezultat, returnând un obiect Job pentru gestionarea execuției. Acest builder implementează modelul fire-and-forget: corutina începe lucrul într-un fir de fundal și se termină automat. Conform documentației JetBrains, 2024, launch este modul principal de lansare a sarcinilor paralele în Kotlin Coroutines.
Principalele puncte
launch — este o funcție de extensie Kotlin, disponibilă prin importul kotlinx.coroutines, care creează o nouă corutină într-un CoroutineScope specificat. Spre deosebire de funcțiile obișnuite, codul din interiorul launch se execută concurent — corutina se poate suspenda (suspend) fără a bloca firul de execuție și se poate relua mai târziu.
Builder-ul launch este un bloc fundamental de construcție al modelului de corutine Kotlin. El nu returnează o valoare calculată, dar returnează un obiect Job care permite controlarea execuției corutinei. Toate corutinele copil lansate prin launch în interiorul unei alte corutine sunt legate de cea părinte.
Builder-ul launch este definit ca o funcție inline cu mai mulți parametri: CoroutineScope, CoroutineContext, CoroutineStart și suspend-block. Parametrii au valori implicite, ceea ce face launch convenabil pentru scenariile tipice.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
Parametrul context acceptă un CoroutineContext care combină dispecerul, gestionarul de excepții și un element denumit. Cel mai des se transmit Dispatchers.IO, Dispatchers.Main sau SupervisorJob pentru izolarea erorilor.
Job — obiectul returnat care reprezintă ciclul de viață al corutinei. Job poate fi în stările: New, Active, Completing, Completed, Cancelling, Cancelled. Fiecare stare reflectă statusul execuției și permite reacționarea la schimbări.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Progres: $i")
}
}
println("Job este activ: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job este anulat: ${job.isCancelled}")
Job suportă ierarhia: dacă corutina părinte este anulată, toate corutinele copil sunt anulate automat. SupervisorJob modifică acest comportament — corutinele copil nu sunt anulate la eroarea uneia dintre ele.
Concurența structurată înseamnă că fiecare corutină este lansată într-un CoroutineScope specific, iar scope-ul nu se va finaliza până când toate corutinele copil nu își termină lucrul. launch suportă pe deplin acest principiu — corutinele lansate în interiorul altei corutine sunt copii ale acesteia.
La lansarea imbricată a launch se formează un arbore de corutine. Corutina părinte așteaptă finalizarea tuturor copiilor, ceea ce garantează o ordine de execuție previzibilă și simplifică gestionarea resurselor.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Copilul 1 s-a finalizat")
}
launch {
delay(500L)
println("Copilul 2 s-a finalizat")
}
println("Toți copiii s-au finalizat înainte de această linie")
}
}
Acest comportament diferă de concurența bazată pe fire de execuție, unde firele copil nu sunt legate de cel părinte. În corutine, părintele nu se finalizează până când toți copiii nu își termină lucrul.
Gestionarea excepțiilor în launch depinde de tipul Job-ului. Pentru un Job obișnuit, excepțiile se propagă la corutina părinte și o anulează. Pentru SupervisorJob sau SupervisorScope, excepțiile sunt izolate — eroarea unei corutine copil nu afectează celelalte.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Prins: ${e.message}")
}
}
scope.launch {
println("Acesta încă rulează datorită SupervisorJob")
}
Pentru gestionarea globală a excepțiilor neprinse se utilizează CoroutineExceptionHandler. Acesta prinde excepțiile care nu au fost gestionate în interiorul corutinei și permite înregistrarea erorii fără crash-ul aplicației.
În Android, launch este utilizat pe scară largă: de la ViewModel la WorkManager. Modelul principal este utilizarea lifecycleScope în Fragment și viewModelScope în ViewModel pentru anularea automată a corutinelor la finalizarea ciclului de viață al componentului.
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 anulează automat corutinele la distrugerea ViewModel-ului. Aceasta elimină scurgerile de memorie și garantează că operațiile de fundal nu continuă după pierderea contextului. Suplimentar, se poate utiliza withContext pentru comutarea între dispeceri.
Întrebări frecvente
launch returnează Job și nu returnează rezultatul execuției, iar async returnează Deferred<T> pentru obținerea rezultatului. launch este utilizat pentru operații fire-and-forget, async — când trebuie să așteptați și să utilizați valoarea returnată.
Apelați job.cancel() pe obiectul Job salvat. Pentru anularea în grup, anulați întregul CoroutineScope prin scope.cancel(). Corutina trebuie să fie cooperativă — să verifice isActive sau să utilizeze funcții suspend verificabile.
Utilizați try-catch în interiorul blocului launch sau transmiteți CoroutineExceptionHandler în CoroutineContext. Pentru izolarea erorilor utilizați SupervisorJob — atunci excepția într-o corutină copil nu va anula celelalte.
Nu, launch este o funcție de extensie a CoroutineScope. Fără scope, corutina nu va putea urma principiul concurenței structurate. Utilizați GlobalScope.launch cu prudență — aceasta creează o corutină fără legătură cu ciclul de viață.
Numărul este limitat de pool-ul de fire al dispecerului. Dispatchers.Default utilizează un număr de fire egal cu numărul de nuclee CPU. Dispatchers.IO suportă până la 64 de fire. La lansarea unui număr mai mare de corutine, acestea sunt puse în coadă.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și