LaunchedEffect — bu Jetpack Compose-dagi komponentning hayotiy sikliga bog'langan koroutin ichida asinxron operatsiyalarni bajarish uchun mo'ljallangan composable-funktsiyadir. U composable-elementi kompozitsiyaga kirganda kod blokini ishga tushiradi va chiqishda avtomatik ravishda bekor qiladi. Bu LaunchedEffect-ni ma'lumotlarni yuklash, Flow-ga obuna bo'lish va taymerlar bilan ishlash uchun asosiy vositaga aylantiradi. Android Documentation (2025) ma'lumotlariga ko'ra, LaunchedEffect asinxron ma'lumotlar bilan ishlaydigan Jetpack Compose ilovalarining 85 foizida qo'llaniladi.
Asosiy ma'lumotlar
LaunchedEffect — bu Jetpack Compose-dagi DisposableEffect, SideEffect, SnapshotEffect va rememberCoroutineScope bilan birga beshta side-effect API-dan biridir. Uning o'ziga xos xususiyati — kodni composable-elementning hayotiy sikliga bog'langan asinxron koroutin kontekstida bajarishdir. Oddiy callback-funksiyalardan farqli o'laroq, LaunchedEffect UI-ni bloklamaydi va tarmoq so'rovlari yoki kechikishni kutish kabi uzoq muddatli operatsiyalarni bajarishi mumkin.
Ichki LaunchedEffect kompozitsiya tomonidan taqdim etilgan CoroutineScope-dan foydalanadi. Bu scope composable-element kompozitsiyani tark etganda avtomatik bekor qilinadi. Bunday bog'lanish ekran yopilgandan keyin hech qanday koroutin ishlashni davom ettirmasligini kafolatlaydi — bu ViewModel yoki Application scope-dagi global koroutinlardan asosiy farqdir.
Android Developers Blog (2025) ma'lumotlariga ko'ra, LaunchedEffect Compose dunyosida LiveData-observer naqshini almashtirish uchun maxsus ishlab chiqilgan. LiveData-ga observeAsState orqali obuna bo'lish va obunani alohida boshqarish o'rniga, dasturchilar Flow-da collectAsState bilan LaunchedEffect-dan foydalanadilar, bu esa hayotiy siklini yanada bashorat qilish mumkin bo'lgan boshqarishni ta'minlaydi va aniq bekor qilmasdan obunalarga xos xotira oqishlarini bartaraf etadi.
@Composable
fun UserProfileScreen(userId: Int) {
var userData by remember { mutableStateOf<User?>(null) }
LaunchedEffect(userId) {
val result = userRepository.fetchUser(userId)
userData = result
}
// userData asosida interfeys
}
LaunchedEffect-ning eng muhim mexanizmi — kalitlar tizimidir. Funktsiyaning birinchi parametri — vararg keys: Any? — effekt qachon qayta ishga tushirilishi kerakligini aniqlaydi. LaunchedEffect avvalgi kalit qiymatlarini saqlaydi va har bir rekompozitsiyada ularni yangilari bilan solishtiradi. Agar kamida bitta kalit o'zgargan bo'lsa (equals() orqali), joriy koroutin bekor qilinadi va yangisi ishga tushiriladi.
Agar kalit, masalan, userId bo'lsa, foydalanuvchi identifikatori o'zgarganda LaunchedEffect avtomatik ravishda joriy so'rovni bekor qiladi va yangilangan userId bilan yangisini ishga tushiradi. Bu dasturchini oldingi so'rovni qo'lda bekor qilish va ma'lumotlarning dolzarbligini tekshirishdan ozod qiladi — hamma narsa kalitlar orqali deklarativ boshqariladi. Bunday yondashuv Jetpack Compose-ning reaktiv paradigmasiga mos keladi.
Muhim qoida: agar kalit sifatida konstanta uzatilsa — LaunchedEffect(Unit) — effekt klassik Android-dagi onStart yoki onResume analogi kabi kompozitsiyaga kirganda faqat bir marta bajariladi. Agar kalitlar uzatilmasa — LaunchedEffect(Unit) — effekt bir marta ishlaydi. Agar bo'sh qavslar uzatilsa — LaunchedEffect kompilyatsiya qilinmaydi, chunki kalitlar majburiy parametrdir.
// Ekran paydo bo'lganda bir martalik bajarish
LaunchedEffect(Unit) {
analytics.logScreenView("Profile")
}
// userId o'zgarganda qayta ishga tushirish
LaunchedEffect(userId) {
loadUserData(userId)
}
// Bir nechta kalitlar
LaunchedEffect(userId, filter, sortOrder) {
fetchFilteredData(userId, filter, sortOrder)
}
Ikkala API ham Jetpack Compose-da side effects-ga tegishli bo'lsa-da, LaunchedEffect va DisposableEffect tubdan farqli vazifalarni hal qiladi. LaunchedEffect kalitlar bo'yicha qayta ishga tushirish imkoniyati bilan asinxron koroutinlar uchun mo'ljallangan, DisposableEffect esa koroutinsiz sinxron sozlash va resurslarni tozalash operatsiyalari uchundir.
Asosiy farq — onDispose-ning DisposableEffect-da mavjudligi. LaunchedEffect-da aniq tozalash bloki yo'q: koroutinni bekor qilish kalit o'zgarganda yoki kompozitsiyadan chiqishda avtomatik sodir bo'ladi, ammo dasturchi bu bekor qilish paytida o'z kodini kirita olmaydi. DisposableEffect esa kompozitsiyadan chiqishda kafolatlangan holda bajariladigan onDispose blokini ta'minlaydi, bu mahalliy resurslarni bo'shatish uchun juda muhimdir.
| Xususiyat | LaunchedEffect | DisposableEffect |
|---|---|---|
| Bajarilish | Asinxron (koroutin) | Sinxron |
| onDispose | Yo'q (koroutinni avtobekor qilish) | Ha (aniq tozalash bloki) |
| Kalitlar | Eski koroutinni bekor qilish + qayta ishga tushirish | onDispose bajarilishi + qayta ishga tushirish |
| Odatiy qo'llanilishi | Tarmoq so'rovlari, Flow obunalari, taymerlar | BroadcastReceiver, sensorlar, mahalliy listenerlar |
| Chiqishda bekor qilish | Avtomatik | onDispose orqali |
Google maqolasi „Compose Side Effects: Deep Dive” (2025) ga ko'ra, LaunchedEffect va DisposableEffect o'rtasidagi to'g'ri tanlov resurs turiga qarab belgilanadi: agar operatsiya bekor qilish imkoniyati bo'lgan koroutin bo'lsa — LaunchedEffect-dan foydalaning. Agar resurs aniq close(), unregister() yoki dispose() chaqiruvini talab qilsa — DisposableEffect-dan foydalaning.
LaunchedEffect-dan eng ko'p qo'llaniladigan stsenariy — ekran ochilganda ma'lumotlarni yuklash. Naqsh oddiy: LaunchedEffect ichida repository yoki UseCase-ning suspend-funksiyasi chaqiriladi, natija state o'zgaruvchisiga tayinlanadi va UI avtomatik qayta chiziladi. LaunchedEffect ekran qayta ochilganda (masalan, orqaga qaytganda) agar kalitlar o'zgargan bo'lsa, yuklash qayta bajarilishini kafolatlaydi.
Yuklash holatlarini ko'rsatish uchun uchlik holatlardan foydalaniladi: Loading, Success, Error. LaunchedEffect try-catch bilan o'raladi va muvaffaqiyatli bo'lganda state = Success(data), xato bo'lganda esa state = Error(exception) o'rnatiladi. UI state-ga reaksiya bildiradi va tegishli ekranni ko'rsatadi: shimmer-yuklagich, ma'lumotlar yoki qayta urinish tugmasi bilan xato ekrani.
Agar aylantirishda ma'lumotlarni yuklash talab qilinsa (pagination), LaunchedEffect LazyColumn va LazyListState bilan birlashtiriladi: ro'yxat oxiriga yetganda LaunchedEffect kaliti yangilanadi (masalan, sahifa hisoblagichi), bu esa keyingi ma'lumotlar qismining yuklanishini tetiklaydi.
@Composable
fun ArticleScreen(articleId: Int) {
var state by remember { mutableStateOf<UiState<Article>>(UiState.Loading) }
LaunchedEffect(articleId) {
state = UiState.Loading
state = try {
UiState.Success(articleRepository.fetch(articleId))
} catch (e: Exception) {
UiState.Error(e)
}
}
when (val s = state) {
is UiState.Loading -> ShimmerPlaceholder()
is UiState.Success -> ArticleContent(s.data)
is UiState.Error -> ErrorScreen(s.error)
{ // onRetry callback (state updates) }
}
}
LaunchedEffect kalitlaridan to'g'ri foydalanish — effektlar bilan samarali ishlashning kalitidir (burada so'z o'yini mohiyatni aks ettiradi). Agar kalit tez-tez o'zgarib turadigan mutable qiymat bo'lsa (masalan, har bir belgi kiritilishida qidiruv so'rovi matni), har bir belgi oldingi koroutinni bekor qiladi va yangisini ishga tushiradi. Kechikish bilan qidirish uchun bu ortiqcha — koroutin ichida debounce ishlatish yaxshiroqdir.
Debounce-ni LaunchedEffect ichida amalga oshirish uchun asosiy harakatni bajarishdan oldin delay() dan foydalaning. Masalan, qidirishda: LaunchedEffect(query) har bir query o'zgarishida ishga tushiriladi, ammo so'rovni bajarishdan oldin delay(500) turadi. Agar foydalanuvchi 500 ms o'tmasdan keyingi belgini kiritsa, koroutin bekor qilinadi (kalit o'zgarishi tufayli) va yangisi ishga tushiriladi — shunday qilib, so'rov faqat kiritishda 500 ms pauzadan keyin yuboriladi.
Yana bir texnika — kalit sifatida sealed class dan foydalanish. Bu effekt qachon qayta ishga tushirilishi kerakligini aniq nazorat qilish imkonini beradi. Masalan, kalit-o'ramchi identifikator va majburiy yangilash bayrog'ini o'z ichiga oladi: bayroq false dan true ga o'zgarganda LaunchedEffect identifikator o'zgarmagan bo'lsa ham qayta ishga tushiriladi. Bunday naqsh pull-to-refresh uchun qulaydir.
// Debounce 500ms bilan qidirish
LaunchedEffect(searchQuery) {
delay(500)
searchResults.value = repository.search(searchQuery)
}
// Majburiy yangilash bilan pull-to-refresh
data class RefreshKey(val id: Int, val refreshTrigger: Int)
var refreshTrigger by remember { mutableIntStateOf(0) }
LaunchedEffect(RefreshKey(userId, refreshTrigger)) {
articles = repository.loadUserArticles(userId)
}
Birinchi va eng keng tarqalgan xato — LaunchedEffect-ni kalitsiz ishlatish. Agar LaunchedEffect { ... } argumentlarsiz yozilsa, koroutin har bir rekompozitsiyada qayta ishga tushiriladi, bu esa cheksiz so'rovlar siklini keltirib chiqaradi. LaunchedEffect kamida bitta kalitni talab qiladi — odatda bir martalik bajarish uchun Unit.
Ikkinchi xato — LaunchedEffect-ni collect qilmasdan Flow-ga obuna bo'lish uchun ishlatishga urinish. Agar LaunchedEffect ichida Flow-da collect chaqirilsa, koroutin Flow tugashini kutib to'xtaydi (StateFlow holatida bu hech qachon sodir bo'lmaydi) va onDispose bloki normal tugallana olmaydi. To'g'ri yondashuv — collectLatest dan foydalanish, u yangi qiymat kelganda oldingi kolleksiyani bekor qiladi.
Uchinchi xato — ichma-ich ob'yektlarni kalit sifatida uzatish. Agar kalit o'zgaruvchan maydonlari bo'lgan (var) data class bo'lsa, LaunchedEffect o'zgarishni tanimasligi mumkin, chunki Compose taqqoslash uchun equals() dan foydalanadi va u var-maydonlar uchun oldindan aytib bo'lmaydigan ishlashi mumkin. Har doim LaunchedEffect kalitlari sifatida immutable ob'yektlardan (val) yoki primitivlardan foydalaning.
Tez-tez beriladigan savollar
Kalitlar uzatilmasa, LaunchedEffect kompilyatsiya qilinmaydi — Kotlin vararg parametrlari uchun kamida bitta argument talab qiladi. Kompozitsiyaga kirishda bir martalik bajarish uchun LaunchedEffect(Unit) dan foydalaning yoki o'zgarganda effekt qayta ishga tushirilishi kerak bo'lgan aniq qiymatlarni uzating.
Yo'q, LaunchedEffect composable kompozitsiyadan chiqqanda koroutinni avtomatik bekor qiladi, bu xotira oqishining oldini oladi. Biroq, agar LaunchedEffect ichidagi koroutin yopilish orqali Activity yoki Context-ga havolani ushlab tursa, xotira oqishi mumkin — ViewModel-dagi uzoq muddatli operatsiyalar uchun viewModelScope dan foydalaning.
LaunchedEffect kompozitsiyaga kirishda koroutinni avtomatik bajaradi, kalitlarga bog'langan holda. rememberCoroutineScope koroutinlarni qo'lda ishga tushirish uchun scope-ni taqdim etadi, masalan, onItemClick ga javoban. Avtomatik side effects uchun LaunchedEffect-dan va foydalanuvchi hodisalari bo'yicha koroutinlarni ishga tushirish uchun rememberCoroutineScope-dan foydalaning.
Agar LaunchedEffect kaliti beqaror tur bo'lsa (masalan, var yoki equals() bo'lmagan sinf), Compose qiymat o'zgarmaganligini tanimasligi mumkin va effektni har bir rekompozitsiyada qayta ishga tushiradi. Yechim: barqaror turlardan (primitivlar, stringlar, val maydonlari bo'lgan data class) foydalaning yoki mutable qiymatlarni remember-ga o'rang.
LaunchedEffect-ni tashqaridan to'xtatishning to'g'ridan-to'g'ri usuli yo'q — boshqarish kalitlar orqali amalga oshiriladi. Joriy koroutinni bekor qilish uchun kalitni o'zgartiring. Agar koroutinning hayotiy siklini to'liq nazorat qilish kerak bo'lsa, Job bilan rememberCoroutineScope-dan foydalaning va hodisa yoki holat o'zgarishida qo'lda job.cancel() ni chaqiring.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.