launch — Coroutine Builder у Kotlin-у који покреће корутину без враћања резултата, враћајући Job објекат за управљање извршењем. Овај builder имплементира образац fire-and-forget: корутина почиње рад у позадинској нити и аутоматски се завршава. Према документацији JetBrains, 2024, launch је основни начин покретања паралелних задатака у Kotlin Coroutines.
Главне тачке
launch — је функција проширења Kotlin-а, доступна преко import kotlinx.coroutines, која креира нову корутину у задатом CoroutineScope-у. За разлику од обичних функција, код унутар launch-а се извршава конкурентно — корутина може да се суспендује (suspend) без блокирања нити и да се настави касније.
Launch builder је фундаментални градивни блок модела корутина у Kotlin-у. Он не враћа израчунату вредност, али враћа Job објекат који омогућава контролу извршења корутине. Све подређене корутине покренуте преко launch-а унутар друге корутине везане су за родитељску.
Launch builder је дефинисан као inline функција са неколико параметара: CoroutineScope, CoroutineContext, CoroutineStart и suspend-block. Параметри имају подразумеване вредности, што чини launch погодним за типичне сценарије.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
Параметар context прихвата CoroutineContext који комбинује диспечера, руковаоца изузецима и именовани елемент. Најчешће се преноси Dispatchers.IO, Dispatchers.Main или SupervisorJob за изолацију грешака.
Job — повратни објекат који представља животни циклус корутине. Job може бити у стањима: New, Active, Completing, Completed, Cancelling, Cancelled. Свако стање одражава статус извршења и омогућава реакцију на промене.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Напредак: $i")
}
}
println("Job је активан: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job је отказан: ${job.isCancelled}")
Job подржава хијерархију: ако се родитељска корутина откаже, све подређене се аутоматски отказују. SupervisorJob мења ово понашање — подређене корутине се не отказују при грешци једне од њих.
Структурисана конкурентност значи да се свака корутина покреће у одређеном CoroutineScope-у, и scope се не завршава док све подређене корутине не заврше рад. launch у потпуности подржава овај принцип — корутине покренуте унутар друге корутине су њене подређене.
При угнежђеном покретању launch-а формира се стабло корутина. Родитељска корутина чека завршетак свих подређених, што гарантује предвидљив редослед извршења и поједностављује управљање ресурсима.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Дете 1 завршено")
}
launch {
delay(500L)
println("Дете 2 завршено")
}
println("Сва деца завршена пре ове линије")
}
}
Ово понашање се разликује од конкурентности засноване на нитима, где подређене нити нису везане за родитељску. У корутинама, родитељ се не завршава док сва деца не заврше рад.
Обрада изузетака у launch-у зависи од типа Job-а. За обичан Job, изузеци се шире на родитељску корутину и отказују је. За SupervisorJob или SupervisorScope, изузеци су изоловани — грешка једне подређене корутине не утиче на остале.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Ухваћено: ${e.message}")
}
}
scope.launch {
println("Ово још увек ради захваљујући SupervisorJob-у")
}
За глобалну обраду нехваћених изузетака користи се CoroutineExceptionHandler. Он хвата изузетке који нису обрађени унутар корутине и омогућава логирање грешке без краш-а апликације.
У Android-у, launch се широко користи: од ViewModel-а до WorkManager-а. Главни образац је коришћење lifecycleScope у Fragment-у и viewModelScope у ViewModel-у за аутоматско отказивање корутина при завршетку животног циклуса компоненте.
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 аутоматски отказује корутине при уништењу ViewModel-а. Ово елиминише цурење меморије и гарантује да се позадинске операције не настављају након губитка контекста. Додатно, може се користити withContext за пребацивање између диспечера.
Често постављана питања
launch враћа Job и не враћа резултат извршења, док async враћа Deferred<T> за добијање резултата. launch се користи за fire-and-forget операције, async — када треба сачекати и искористити повратну вредност.
Позовите job.cancel() на сачуваном Job објекту. За групно отказивање, откажите цео CoroutineScope преко scope.cancel(). Корутина мора бити кооперативна — проверавати isActive или користити проверљиве suspend функције.
Користите try-catch унутар launch блока или проследите CoroutineExceptionHandler у CoroutineContext. За изолацију грешака користите SupervisorJob — тада изузетак у једној подређеној корутини неће отказати остале.
Не, launch је функција проширења CoroutineScope-а. Без scope-а, корутина неће моћи да следи принцип структурисане конкурентности. Користите GlobalScope.launch опрезно — ово ствара корутину без везивања за животни циклус.
Број је ограничен пулом нити диспечера. Dispatchers.Default користи број нити једнак броју CPU језгара. Dispatchers.IO подржава до 64 нити. При покретању већег броја корутина, one се стављају у ред чекања.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође