launch — Kotlin-də nəticə qaytarmadan korutini işə salan, icranı idarə etmək üçün Job obyekti qaytaran Coroutine Builder-dir. Bu builder fire-and-forget nümunəsini tətbiq edir: korutin fon təyində işə başlayır və avtomatik olaraq başa çatır. JetBrains sənədləşməsinə, 2024 görə, launch Kotlin Coroutines-də paralel tapşırıqların işə salınmasının əsas üsuludur.
Əsas məqamlar
launch — kotlinx.coroutines import vasitəsilə əlçatan olan, verilmiş CoroutineScope-da yeni korutin yaradan Kotlin genişləndirmə funksiyasıdır. Adi funksiyalardan fərqli olaraq, launch daxilindəki kod konkurrent şəkildə icra olunur — korutin təyini bloklamadan dayandırıla (suspend) və sonra bərpa oluna bilər.
Launch builder Kotlin korutin modelinin əsas tikinti blokudur. O, hesablanmış dəyəri qaytarmır, lakin korutinin icrasını idarə etməyə imkan verən Job obyektini qaytarır. Başqa bir korutinin daxilində launch vasitəsilə işə salınan bütün uşaq korutinlər valideynə bağlanır.
Launch builder bir neçə parametrə malik inline funksiya kimi təyin olunur: CoroutineScope, CoroutineContext, CoroutineStart və suspend-blok. Parametrlərin standart dəyərləri var ki, bu da launch-ı tipik ssenarilər üçün əlverişli edir.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
context parametri dispetçeri, istisna işləyicisini və adlandırılmış elementi birləşdirən CoroutineContext qəbul edir. Ən çox Dispatchers.IO, Dispatchers.Main və ya səhvləri təcrid etmək üçün SupervisorJob ötürülür.
Job — korutinin həyat dövrünü təmsil edən qaytarılan obyekt. Job aşağıdakı hallarda ola bilər: New, Active, Completing, Completed, Cancelling, Cancelled. Hər bir vəziyyət icra statusunu əks etdirir və dəyişikliklərə reaksiya verməyə imkan verir.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Proqress: $i")
}
}
println("Job aktivdir: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job ləğv olunub: ${job.isCancelled}")
Job iyerarxiyanı dəstəkləyir: əgər valideyn korutin ləğv olunarsa, bütün uşaqlar avtomatik ləğv olunur. SupervisorJob bu davranışı dəyişir — uşaq korutinlər onlardan birinin xətası ilə ləğv olunmur.
Strukturlaşdırılmış konkurrentlik o deməkdir ki, hər bir korutin müəyyən CoroutineScope-da işə salınır və bütün uşaq korutinlər işini bitirməyincə scope başa çatmır. launch bu prinsipi tam dəstəkləyir — başqa korutinin daxilində işə salınan korutinlər onun uşaqlarıdır.
İç-içə launch işə salındıqda korutinlər ağacı əmələ gəlir. Valideyn korutin bütün uşaqların bitməsini gözləyir ki, bu da proqnozlaşdırıla bilən icra sırasını təmin edir və resurs idarəçiliyini sadələşdirir.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Uşaq 1 tamamlandı")
}
launch {
delay(500L)
println("Uşaq 2 tamamlandı")
}
println("Bütün uşaqlar bu sətirdən əvvəl tamamlandı")
}
}
Bu davranış, uşaq təyimlərin valideynə bağlı olmadığı təyim əsaslı konkurrentlikdən fərqlənir. Korutinlərdə valideyn başa çatmır, bütün uşaqlar işini bitirməyincə.
Launch-da istisnaların işlənməsi Job növündən asılıdır. Adi Job üçün istisnalar valideyn korutinə yayılır və onu ləğv edir. SupervisorJob və ya SupervisorScope üçün istisnalar təcrid olunur — bir uşaq korutinin xətası digərlərinə təsir etmir.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Tutuldu: ${e.message}")
}
}
scope.launch {
println("Bu, SupervisorJob sayəsində hələ də işləyir")
}
Tutulmamış istisnaların qlobal işlənməsi üçün CoroutineExceptionHandler istifadə olunur. O, korutin daxilində işlənməmiş istisnaları tutur və proqramın çökmədən xətanı qeydə almağa imkan verir.
Android-də launch hər yerdə tətbiq olunur: ViewModel-dən WorkManager-ə qədər. Əsas nümunə — komponentin həyat dövrü başa çatdıqda korutinlərin avtomatik ləğvi üçün Fragment-də lifecycleScope və ViewModel-də viewModelScope istifadəsidir.
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 məhv olduqda korutinləri avtomatik ləğv edir. Bu, sızmaları aradan qaldırır və fon əməliyyatlarının kontekst itirildikdən sonra davam etməməsinə zəmanət verir. Əlavə olaraq dispetçirlər arasında keçid üçün withContext istifadə oluna bilər.
Tez-tez verilən suallar
launch Job qaytarır və icra nəticəsini qaytarmır, async isə nəticə əldə etmək üçün Deferred<T> qaytarır. launch fire-and-forget əməliyyatları üçün, async isə qaytarılan dəyəri gözləmək və istifadə etmək lazım olduqda istifadə olunur.
Saxlanılmış Job obyektində job.cancel() çağırın. Qrup şəklində ləğv etmək üçün scope.cancel() vasitəsilə bütün CoroutineScope-u ləğv edin. Korutin kooperativ olmalıdır — isActive yoxlamalı və ya yoxlanıla bilən suspend funksiyaları istifadə etməlidir.
Launch bloku daxilində try-catch istifadə edin və ya CoroutineContext-də CoroutineExceptionHandler ötürün. Səhvləri təcrid etmək üçün SupervisorJob istifadə edin — onda bir uşaq korutindəki istisna qalanlarını ləğv etməyəcək.
Xeyr, launch CoroutineScope-un genişləndirmə funksiyasıdır. Scope olmadan korutin strukturlaşdırılmış konkurrentlik prinsipinə əməl edə bilməz. GlobalScope.launch-dan ehtiyatla istifadə edin — bu, həyat dövrünə bağlı olmayan korutin yaradır.
Sayı dispetçerin təyim hovuzu ilə məhdudlaşır. Dispatchers.Default CPU nüvələrinin sayına bərabər sayda təyim istifadə edir. Dispatchers.IO 64 təyimə qədər dəstəkləyir. Daha çox korutin işə salındıqda onlar növbəyə düzülür.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun