DisposableEffect — bu nima, resurslarni bo'shatish Jetpack Compose-da

Muallif: IT Sectr Nashr etilgan: 2026-06-30 O'qish vaqti: 9 daq

DisposableEffect — Jetpack Compose-da composable-funksiya bo'lib, aniq ishga tushirish va keyinchalik resurslarni tozalashni talab qiladigan operatsiyalar uchun mo'ljallangan. Boshqa side-effect API-lardan farqli o'laroq, DisposableEffect onDispose blokini taqdim etadi, u komponent kompozitsiyadan chiqqanda yoki kalit o'zgarganda kafolatlangan holda bajariladi. Bu uni mahalliy obunalar, sensor tinglovchilari va apparat resurslari bilan ishlash uchun ajralmas qiladi. Android Developers Documentation (2025)-ga ko'ra, DisposableEffect Activity hayotiy tsiklidagi onStart/onStop-ga o'xshash setup/teardown juftligi talab qilinadigan barcha stsenariylarda foydalanish tavsiya etiladi.

Asosiy ma'lumotlar

  • DisposableEffect — resurslarni sozlash va kafolatlangan tozalash uchun side-effect API.
  • onDispose — kompozitsiyadan chiqish yoki kalit o'zgarishida bajariladigan majburiy blok.
  • Sinxronlik — LaunchedEffect-dan farqli o'laroq, DisposableEffect korutinsiz sinxron ishlaydi.
  • Tozalash — odatiy stsenariylar: LiveData-dan obunani bekor qilish, soketlarni yopish, BroadcastReceiver ro'yxatdan o'tkazishni bekor qilish.
  • Kalitlar — kalit o'zgarganda eski qiymat uchun onDispose bajariladi va yangi qiymat bilan qayta ishga tushiriladi.

Jetpack Compose-da DisposableEffect nima

DisposableEffect — Jetpack Compose-da resurslarni boshqarish uchun asosiy vositadir. Uning asosiy xususiyati — composable-komponentning hayotiy tsikli tugaganda onDispose blokining kafolatlangan chaqiruvidir. Bu xatti-harakat Android ishlab chiqish uchun juda muhim, chunki yopilmagan tizim xizmatlariga obunalar xotira oqishiga va ilovaning ishdan chiqishiga olib kelishi mumkin.

Korutin kontekstida asinxron ishlaydigan LaunchedEffect-dan farqli o'laroq, DisposableEffect sinxron bajariladi. Bu uning ichida suspend-funksiyalarni chaqirib bo'lmasligini anglatadi. Sinxronlik bashorat qilish imkoniyatini ta'minlaydi: ishga tushirish kodi birinchi renderdan oldin, tozalash kodi esa komponent xotiradan o'chirilishidan oldin bajarilishiga ishonch hosil qilishingiz mumkin.

Jetpack Compose Hujjatlariga (2025) ko'ra, DisposableEffect to'rtta asosiy stsenariyda qo'llanilishi kerak: (1) tizim xizmatlariga obuna bo'lish (sensorlar, LocationManager), (2) BroadcastReceiver ro'yxatdan o'tkazish, (3) korutinlarni qo'llab-quvvatlamaydigan callback-ga asoslangan kutubxonalar bilan ishlash, (4) Compose komponentlarini AndroidView orqali Legacy View tizimlariga bog'lash.

kotlin
class SensorManager(private val context: Context) {
    fun startListening(callback: (Float) -> Unit) { /* register */ }
    fun stopListening() { /* cancel */ }
}

@Composable
fun SensorDisplay() {
    val sensorManager = remember { SensorManager(context) }
    var value by remember { mutableStateOf(0f) }
    
    DisposableEffect(Unit) {
        sensorManager.startListening { value = it }
        onDispose { sensorManager.stopListening() }
    }
    
    Text("Sensor: $value")
}

DisposableEffect onDispose bilan qanday ishlaydi

DisposableEffect-ning ichki mexanikasi kompozitsiyaning hayotiy tsikl fazalariga asoslanadi. Composable-komponent kompozitsiyaga kirganda, DisposableEffect uzatilgan kod blokini chaqiradi. Bu blok onDispose lambdasini o'z ichiga olgan DisposableEffectResult obyektini qaytaradi. Kompozitsiya bu natijani saqlaydi va komponent kompozitsiyani tark etganda onDispose-ni chaqiradi — sababidan qat'iy nazar (navigatsiya, ota-ona holatining o'zgarishi, LazyColumn-dan o'chirilishi).

DisposableEffect-dagi kalit mexanizmi LaunchedEffect bilan bir xil ishlaydi: har qanday kalit o'zgarganda avval eski holat uchun onDispose bajariladi, so'ng ishga tushirish bloki yangi kalitlar bilan qayta ishga tushadi. Bu parametrlar o'zgarganda resursni qayta konfiguratsiya qilish imkonini beradi. Masalan, kalit socket URL-i bo'lsa, uning o'zgarishi bilan eski socket yopiladi va yangi socket ochiladi.

Muhim: onDispose bloki DisposableEffect-ning majburiy elementidir. Blok ichida onDispose chaqirilmasa, kod kompilyatsiya qilinmaydi. Kompilyatorning bu talabi dasturchi resursni tozalashni unutmasligini kafolatlaydi, bu obunalarni qo'lda boshqarishda tez-tez uchraydigan xatodir.

kotlin
// Kalit bilan to'g'ri foydalanish
DisposableEffect(sensorType) {
    val sensor = sensorManager.getDefaultSensor(sensorType)
    sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
    
    onDispose {
        sensorManager.unregisterListener(listener)
    }
}

// Bir DisposableEffect-da bir nechta resurslar
DisposableEffect(Unit) {
    context.registerReceiver(receiver, intentFilter)
    lifecycle.addObserver(observer)
    
    onDispose {
        context.unregisterReceiver(receiver)
        lifecycle.removeObserver(observer)
    }
}

DisposableEffect xotira oqishiga qarshi

Android ilovalarida xotira oqishi ko'pincha ekran yopilgandan keyin Activity yoki Context-ga havolani saqlaydigan ro'yxatdan o'tmagan tinglovchilar va obunalar tufayli yuzaga keladi. DisposableEffect bu muammoni framework darajasida hal qiladi: agar dasturchi tinglovchini ro'yxatdan o'tkazish uchun DisposableEffect ishlatgan bo'lsa, onDispose komponentning tugashining istalgan stsenariysida obunani kafolatlangan holda bekor qiladi.

Bu, ayniqsa, elementlar skroll paytida doimiy ravishda yaratiladigan va yo'q qilinadigan LazyColumn va LazyGrid uchun juda muhimdir. DisposableEffect bo'lmasa, ko'rinish maydonidan chiqib ketadigan har bir element faol obunani qoldiradi. DisposableEffect bilan onDispose har bir tushirilgan element uchun chaqiriladi va resurslar element ekranni tark etishi bilanoq bo'shatilishini kafolatlaydi.

Android Performance Patterns (Google, 2025)-ga ko'ra, barcha mahalliy obunalar uchun DisposableEffect ishlatilishi Compose ilovalarida xotira oqishlari sonini hayotiy tsikl callbacklari bilan qo'lda boshqarishga nisbatan 60–70% ga kamaytiradi. Tizim o'zi kompozitsiyadan chiqish momentini kuzatadi va hatto ekranning favqulodda yopilishida ham onDispose bajarilishini kafolatlaydi.

ResursDisposableEffect nima qiladiDisposableEffectsiz
BroadcastReceiverregister + onDispose → unregisterReceiver faol qoladi
SensorManagerregisterListener + onDispose → unregisterSensor ma'lumot yuborishda davom etadi
Observable (Flow emas)subscribe + onDispose → unsubscribeCallback havolani saqlaydi
TextureView / SurfaceViewsetCallback + onDispose → removeCallbackCallback oqishi
Socket / Channelopen + onDispose → closeUlanish ochiq qoladi

DisposableEffect orqali sensorlarga obuna bo'lish

DisposableEffect-ning eng yorqin misollaridan biri — qurilma sensorlari bilan ishlash (akselerometr, giroskop, magnitometr). Sensorlar ish oxirida majburiy ro'yxatdan o'tkazishni bekor qilishni talab qiladi, aks holda ular ekran yopilgandan keyin ham batareya quvvatini iste'mol qilishda va ma'lumot yuborishda davom etadilar.

Amaliy misol: og'ish burchagini o'lchaydigan ilova. DisposableEffect(Unit) komponent paydo bo'lganda akselerometr tinglovchisini ro'yxatdan o'tkazadi va onDispose-da ro'yxatdan o'tkazishni bekor qiladi. Sensor ma'lumotlari mutableStateOf orqali holatga uzatiladi, bu esa UI-ni avtomatik yangilaydi. Ekran LazyColumn-da skroll qilinsa va element yo'qolsa, onDispose darhol ishga tushadi — sensor bu element uchun ma'lumot yuborishni to'xtatadi.

Sensor turi o'zgarganda (masalan, akselerometrdan giroskopga) sensorType kaliti o'zgaradi, onDispose eski obunani bekor qiladi va yangi DisposableEffect bloki yangi sensor ro'yxatdan o'tkazadi. Kalitlar bo'lmasa, qaysi sensor avval ro'yxatdan o'tganini qo'lda tekshirish va to'g'ri listener bilan unregisterListener chaqirish kerak bo'ladi — bu xatolarga olib kelishi mumkin.

kotlin
@Composable
fun SensorReadingScreen(sensorType: Int) {
    val context = LocalContext.current
    val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    var sensorValue by remember { mutableStateOf(0f) }
    
    DisposableEffect(sensorType) {
        val sensor = sensorManager.getDefaultSensor(sensorType)
        val listener = SensorEventListener { event, _ ->
            sensorValue = event.values[0]
        }
        sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
        
        onDispose {
            sensorManager.unregisterListener(listener)
        }
    }
    
    Text("Qiymat: $sensorValue")
}

DisposableEffect orqali BroadcastReceiver ro'yxatdan o'tkazish

BroadcastReceiver — majburiy register / unregister juftligini talab qiladigan klassik API namunasidir. Compose ilovasida DisposableEffect ma'lum bir ekranning ishlash muddati davomida qabul qilgichni ro'yxatdan o'tkazish uchun juda mos keladi. Ekranga kirganda, BroadcastReceiver kerakli IntentFilter bilan ro'yxatdan o'tkaziladi, chiqqanda esa onDispose-da avtomatik bekor qilinadi.

Odatiy stsenariy — tarmoq holatini kuzatish. DisposableEffect ConnectivityManager-da tarmoq ulanishidagi o'zgarishlar haqida xabardor qiladigan qabul qilgichni ro'yxatdan o'tkazadi. Holat o'zgarganda (WiFi / mobil ma'lumotlar / tarmoq yo'q) composable holati yangilanadi va UI tegishli ko'rsatkichni aks ettiradi. Ekran yopilganda, onDispose ro'yxatdan o'tkazishni kafolatlangan holda bekor qiladi — hatto ilova fon rejimiga o'tsa ham.

ContextCompat.registerReceiver va RECEIVER_EXPORTED / RECEIVER_NOT_EXPORTED bayrog'i (Android 14+) bilan qabul qilgichlar uchun DisposableEffect ishlatilishi majburiy bo'ladi, chunki tizim qabul qilgichning harakat doirasini aniq ko'rsatishni talab qiladi. DisposableEffect harakat doirasining ekranning ishlash muddati bilan cheklanganligini kafolatlaydi, bu esa Android-ning yangi versiyalarining xavfsizlik talablariga mos keladi.

kotlin
@Composable
fun NetworkStatusBanner() {
    val context = LocalContext.current
    var isConnected by remember { mutableStateOf(true) }
    
    DisposableEffect(Unit) {
        val receiver = BroadcastReceiver { _, _ ->
            val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            isConnected = cm.getActiveNetwork() != null
        }
        IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).let { filter ->
            context.registerReceiver(receiver, filter)
        }
        
        onDispose {
            context.unregisterReceiver(receiver)
        }
    }
    
    if (!isConnected) { ... }
}

DisposableEffect bilan odatiy xatolar

Birinchi muhim xato — onDispose chaqirilmasligi. DisposableEffect bloki ichidagi kod onDispose-ni chaqirishi kerak, aks holda kompilyatsiya xatosi yuz beradi. Biroq, dasturchilar ba'zan onDispose-ni shart ichiga joylashtirish orqali buni chetlab o'tishga harakat qilishadi: if (condition) { onDispose { ... } }. Bunday kod kompilyatsiya qilinadi, lekin shart bajarilmasa onDispose ro'yxatdan o'tkazilmaydi — resurs hech qachon bo'shatilmaydi.

Ikkinchi xato — DisposableEffect-ni asinxron operatsiyalar uchun ishlatish. DisposableEffect sinxron bo'lgani uchun uning ichida delay() yoki await() chaqiruvlarini yozib bo'lmaydi. Agar keyingi tozalash bilan asinxron ishga tushirish kerak bo'lsa, LaunchedEffect (ma'lumot yuklash uchun) va DisposableEffect (mahalliy resurslarni sozlash/tozalash uchun) kombinatsiyasidan yoki rememberCoroutineScope bilan alohida mexanizmdan foydalaning.

Uchinchi xato — DisposableEffect ichida remembersiz yangi obyektlar yaratish. Agar effekt ichida har chaqiruvda obyektlar (sensor, listener, qabul qilgich) yaratilsa va kalitlar tez-tez o'zgarsa, bu haddan tashqari ko'p obyekt yaratilishiga va axlat yig'ilishiga olib keladi. Obyektlarni yaratishni remember yoki remember { ... } bilan DisposableEffect-dan tashqariga chiqarish, effekt ichida esa faqat ro'yxatdan o'tkazish va bekor qilish yaxshiroqdir.

Tez-tez beriladigan savollar

DisposableEffect va LaunchedEffect o'rtasidagi farq nima?

DisposableEffect sinxron ishlaydi va resurslarni aniq tozalash uchun onDispose-ni taqdim etadi. LaunchedEffect korutinda asinxron ishlaydi va kalit o'zgarganda yoki kompozitsiyadan chiqqanda uni avtomatik bekor qiladi. Agar resurs cleanup metodini (close, unregister, dispose) chaqirishni talab qilsa — DisposableEffect ishlating. Agar operatsiya suspend-funksiya bo'lsa — LaunchedEffect ishlating.

DisposableEffect-da onDispose bloki majburiymi?

Ha, onDispose majburiy — Kotlin kompilyatori uni DisposableEffect bloki ichida chaqirishni talab qiladi. Agar onDispose chaqirilmasa, kod kompilyatsiya qilinmaydi. Bu dasturchilarning e'tiborsizligini oldini olish va har bir ochiq resurs kompozitsiyadan chiqqanda yopilishini kafolatlash uchun ataylab qilingan.

DisposableEffect ichida xatolarni qanday boshqarish mumkin?

DisposableEffect bloki ichida try-catch ishlating. Agar resursni ro'yxatdan o'tkazish istisno yaratishi mumkin bo'lsa (masalan, sensor topilmadi), uni try bilan o'rab oling va xatoni UI-da alohida holat orqali boshqaring. onDispose ishga tushirish muvaffaqiyatidan qat'iy nazar chaqirilishi kerak — uni finally blokiga yoki try bo'limining oxiriga joylashtiring.

Flow-ga obuna bo'lish uchun DisposableEffect ishlatish mumkinmi?

Tavsiya etilmaydi. Flow uchun LaunchedEffect-ni collectLatest bilan yoki .collectAsState() metodini Lifecycle.repeatOnLifecycle bilan ishlatish yaxshiroqdir. DisposableEffect suspend-funksiyalarni qo'llab-quvvatlamaydi, shuning uchun uning ichida Flow-ga obuna bo'lish CoroutineScope orqali alohida korutin ishga tushirishni talab qiladi, bu esa kodni murakkablashtiradi va oqish xavfini oshiradi.

Bitta composable-da nechta DisposableEffect bo'lishi mumkin?

Cheklov yo'q, lekin bog'liq resurslarni bir DisposableEffect-da bir nechta operatsiya va bitta onDispose bilan guruhlash tavsiya etiladi. Agar resurslar mustaqil bo'lsa (masalan, sensor va BroadcastReceiver), ularni turli kalitlar bilan alohida DisposableEffect-larga bo'lish yaxshiroqdir — bu disk raskadrovkani osonlashtiradi va bir kalit o'zgarganda barcha resurslarning istalmagan qayta yaratilishining oldini oladi.

Xulosa

  • DisposableEffect — onDispose orqali kafolatlangan tozalash bilan sinxron ishga tushirish uchun Jetpack Compose side-effect API-si.
  • onDispose — kompozitsiyadan chiqish yoki kalit o'zgarishida bajariladigan, xotira oqishining oldini oluvchi majburiy blok.
  • Kalitlar — kalit o'zgarganda avval eski qiymat uchun onDispose bajariladi, so'ng yangi qiymat bilan qayta ishga tushiriladi.
  • Sinxronlik — DisposableEffect sinxron bajariladi, suspend-funksiyalar uning ichida mavjud emas.
  • Odatiy stsenariylar — BroadcastReceiver, sensorlar, mahalliy tinglovchilar, callback-ga asoslangan kutubxonalar, AndroidView integratsiyasi.
  • Oqishlar — DisposableEffect xotira oqishlari sonini hayotiy tsikl callbacklari bilan qo'lda boshqarishga nisbatan 60–70% ga kamaytiradi.
  • Xatolar — asosiy xavflar: onDispose-ni shartli chaqirish, async operatsiyalar uchun ishlatish, effekt ichida remembersiz obyekt yaratish.

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.

Loyihani muhokama qilish

Shuningdek o'qing