viewModelScope: bu nima, ViewModel-ga bog'lanishi va Android-da ishlashi

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

viewModelScope — bu androidx.lifecycle kutubxonasidan o'rnatilgan CoroutineScope bo'lib, u ViewModel-ning hayotiy sikliga bog'langan va uni tozalashda avtomatik ravishda bekor qilinadi. Google Android Developers, 2025 ma'lumotlariga ko'ra, viewModelScope MVVM arxitekturasida korutinlarni ishga tushirishning standart mexanizmi bo'lib, xotira oqishi xavfisiz asinxron operatsiyalar bilan xavfsiz ishlashni ta'minlaydi. ViewModelScope sukut bo'yicha Dispatchers.Main dan foydalanadi va uning ichidagi barcha IO operatsiyalari withContext orqali bajarilishi kerak.

Asosiy fikrlar

  • viewModelScope — lifecycle-viewmodel-ktx dan CoroutineScope, ViewModel-ning onCleared() da bekor qilinadi
  • Dispatchers.Main — sukut bo'yicha dispetcher, shuning uchun korutinlar ichida UI yangilanishlari xavfsiz
  • onCleared — callback, chaqirilganda viewModelScope barcha faol korutinlarni avtomatik bekor qiladi
  • clear() vs onCleared() — clear() freymvork tomonidan onCleared dan oldin chaqiriladi, bu scope-ning bekor qilinishini kafolatlaydi
  • launch — viewModelScope da fire-and-forget operatsiyalari uchun korutinlarni ishga tushirishning asosiy usuli

Android-da viewModelScope nima?

viewModelScope — bu ViewModel interfeysiga extension xususiyati bo'lib, lifecycle-viewmodel-ktx kutubxonasida (2.1.0 versiyasidan boshlab) qo'shilgan. U ViewModel-ning hayotiy sikliga bog'langan tayyor CoroutineScope ni ta'minlaydi.

kotlin
// Ichki tuzilma (soddalashtirilgan)
val ViewModel.viewModelScope: CoroutineScope
    get() {
        val scope = this.getTag(JOB_KEY)
        if (scope != null) return scope
        return CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
            .also { setTag(JOB_KEY, it) }
    }

Scope birinchi murojaatda dangasa (lazy) tarzda yaratiladi va setTag orqali keshlanadi. SupervisorJob ishlatiladi, ya'ni bitta farzand korutinadagi istisno qolganlarini bekor qilmaydi. Sukut bo'yicha dispetcher Dispatchers.Main.immediate bo'lib, agar chaqiruv allaqachon Main da bo'lsa, qo'shimcha dispetcherizatsiyasiz kodni asosiy oqimda bajaradi.

viewModelScope tozalash haqida bildirishnomani qanday oladi

ViewModel hayotiy siklini tark etganda (Activity tugagan yoki Fragment o'chirilgan), sistem clear() ni chaqiradi, u onCleared() ni ishga tushiradi. Bu callback da viewModelScope o'z Job ini bekor qiladi, bu rekursiv ravishda barcha faol korutinlarni tugatadi. Mexanizm Closeable interfeysi orqali amalga oshiriladi, bunda scope-ning Job i avtomatik yopish uchun resurs sifatida ro'yxatga olinadi.

viewModelScope qanday ishlaydi: ViewModel-ning hayotiy sikliga bog'lanish

viewModelScope ning ViewModel-ning hayotiy sikliga bog'lanish mexanizmi teglash va onCleared callback iga asoslanadi. Keling, buni bosqichma-bosqich ko'rib chiqaylik.

1-qadam: Birinchi murojaatda scope ni yaratish

ViewModel viewModelScope.launch { ... } ni bajarganida, getter JOB_KEY tegi ostida saqlangan scope mavjudligini tekshiradi. Agar scope hali yaratilmagan bo'lsa — CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) ning yangi nusxasi yaratiladi. Scope ichki teg xaritasi orqali ViewModel ichida saqlanadi.

2-qadam: Korutinlarning hayotiy sikli

viewModelScope.launch yoki viewModelScope.async orqali ishga tushirilgan barcha korutinlar SupervisorJob scope iga farzand bo'ladi. Ular asosiy oqimda ishlaydi (agar withContext orqali boshqa dispetcher ko'rsatilmagan bo'lsa). ViewModel tirik ekan — korutinlar faol, to'xtatilgan yoki tugagan bo'lishi mumkin.

3-qadam: onCleared da bekor qilish

Sistem ViewModel ni yo'q qilganda, ViewModel.clear() chaqiriladi. clear() ichida quyidagilar sodir bo'ladi:

  • Foydalanuvchi mantig'i uchun onCleared() chaqiruvi
  • addCloseable orqali ro'yxatdan o'tgan barcha Closeable resurslarning yopilishi
  • viewModelScope Job i Cancelled holatiga o'tadi
  • Barcha farzand korutinlar rekursiv bekor qilinadi
  • Axlat yig'uvchi uchun scope ga havolalarni bo'shatish

Ekran rotatsiyasiga chidamlilik

Ekran aylantirilganda Activity qayta yaratiladi, ammo ViewModel saqlanadi (ViewModelStoreOwner tufayli). Bu viewModelScope faol qoladi va korutinlar uzilishlarsiz ishlashda davom etadi degani. Activity qayta yaratilgandan so'ng, xuddi shu ViewModel (va xuddi shu scope) qayta ishlatiladi — ma'lumotlarni yuklash qaytadan boshlamaydi.

MVVM arxitekturasida viewModelScope

MVVM (Model-View-ViewModel) — Google tomonidan Android ilovalari uchun tavsiya etilgan arxitekturadir. viewModelScope unda asinxron operatsiyalarni bajaruvchi sifatida markaziy o'rinni egallaydi.

viewModelScope ning arxitektura qatlamlaridagi roli

QatlamKomponentviewModelScope roli
UIActivity / FragmentViewModel dan StateFlow/LiveData ni kuzatadi
ViewModelViewModelviewModelScope orqali korutinlarni ishga tushiradi, UI holatini boshqaradi
RepositoryRepositoryviewModelScope korutinlaridan chaqiriladigan suspend-funksiyalarni qabul qiladi
DataDAO / ApiHaqiqiy so'rovlarni bajaradi (Room, Retrofit)

ViewModel viewModelScope orqali korutinlarni ishga tushiradi, ularning ichida Repository ning suspend-funksiyalarini chaqiradi. Natija UI qatlami tomonidan kuzatiladigan StateFlow ga aylantiriladi. Bu sxema mas'uliyatlarning aniq bo'linishini va har bir qatlamning mustaqil sinovdan o'tkazilishini ta'minlaydi.

Nega viewModelScope ViewModel da, Fragment da emas

Agar korutinlar Fragment dan ishga tushirilganda, ekran aylantirilganda ular Fragment ning yo'q qilinishi bilan bekor qilinardi. ViewModel rotatsiyadan omon qoladi, shuning uchun uning scope ida ishga tushirilgan korutinlar bajarilishda davom etadi. Bu viewModelScope ning lifecycleScope dan ma'lumotlarni yuklashdagi asosiy ustunligidir.

viewModelScope dan foydalanish misollari

Kotlin tilidagi Android ilovasida viewModelScope dan foydalanishning uchta amaliy ssenariysini ko'rib chiqamiz.

Misol 1: ViewModel yaratilganda ma'lumotlarni yuklash

kotlin
class ProfileViewModel(
    private val repo: ProfileRepository
) : ViewModel() {

    private val _profile = MutableStateFlow<Profile?>(null)
    val profile: StateFlow<Profile?> = _profile

    init {
        loadProfile()
    }

    private fun loadProfile() {
        viewModelScope.launch {
            val result = repo.getProfile()
            _profile.value = result
        }
    }
}

init blokida darhol profil yuklanishi boshlanadi. Korutina sukut bo'yicha asosiy oqimda bajariladi. Repozitoriy o'zining suspend-funksiyasi ichida tarmoq so'rovi uchun withContext(Dispatchers.IO) dan foydalanadi, shuning uchun ViewModel oqimlarni almashtirish bilan shug'ullanmaydi.

Misol 2: Xatolarni sealed class orqali qayta ishlash

kotlin
sealed class UiState {
    object Loading : UiState()
    data class Success(val data: List<Item>) : UiState()
    data class Error(val message: String) : UiState()
}
kotlin
fun fetchItems() {
    _state.value = UiState.Loading
    viewModelScope.launch {
        try {
            val items = repo.getItems()
            _state.value = UiState.Success(items)
        } catch (e: Exception) {
            _state.value = UiState.Error(e.message ?: "Unknown error")
        }
    }
}

UI holati sealed class UiState orqali tasvirlanadi. ViewModel har bir o'zgarishda state ni yangilaydi. Fragment StateFlow ga obuna bo'lib, faqat joriy holatga reaksiya beradi, takroriy rotatsiyalarda eskirgan chaqiruvlarni e'tiborsiz qoldiradi.

Misol 3: Yangi so'rovda oldingi korutinani bekor qilish

kotlin
private var searchJob: Job? = null

fun search(query: String) {
    searchJob?.cancel()
    searchJob = viewModelScope.launch {
        delay(300)
        val results = repo.search(query)
        _searchResults.value = results
    }
}

Har bir yangi qidiruv so'rovida oldingi korutina bekor qilinadi. delay(300) debounce ni amalga oshiradi — qidiruv faqat kiritishda 300 ms pauzadan keyin bajariladi. Bu server yukini kamaytiradi va eskirgan natijalarning oldini oladi.

viewModelScope vs lifecycleScope: qachon nimani tanlash

Ikkala scope ham AndroidX Lifecycle kutubxonasi tomonidan taqdim etiladi, ammo turli hayotiy sikllarga bog'langan. Ularning o'rtasida tanlov vazifa turiga bog'liq.

Scope larning solishtiruvi

XususiyatviewModelScopelifecycleScope
EgasiViewModelLifecycleOwner (Activity/Fragment)
Rotatsiyada bekor qilishYo'q (ViewModel saqlanadi)Ha (Activity qayta yaratiladi)
Sukut bo'yicha dispetcherDispatchers.Main.immediateDispatchers.Main.immediate
MavjudViewModelActivity, Fragment, Service
Oddiy ssenariyMa'lumotlarni yuklash, biznes mantiqUI o'zaro aloqasi, animatsiyalar, snackbarlar

Google tavsiyalari

Google ma'lumotlarni yuklash va qayta ishlash bilan bog'liq barcha vazifalar uchun viewModelScope dan foydalanishni tavsiya qiladi. lifecycleScope UI hayotining aniq bir daqiqasiga bog'liq operatsiyalar uchun qo'llanilishi kerak — masalan, ekranning birinchi paydo bo'lishida animatsiyani ishga tushirish yoki ekrandan chiqishda to'xtatilishi kerak bo'lgan Location yangilanishlariga obuna bo'lish.

viewModelScope bilan ishlashda tipik xatolar

Hatto Android ning yaxshi hujjatlangan API larida ham dasturchilar xarakterli xatolarga yo'l qo'yadilar. To'rtta eng ko'p uchraydigan muammoni ko'rib chiqamiz.

Xato 1: Scope bekor qilingandan keyin UI ni yangilash

Eng makkor xato — ViewModel tozalangandan keyin StateFlow yoki LiveData ni yangilashga urinish. viewModelScope onCleared() da bekor qilingan bo'lsa-da, korutina haqiqiy bekor qilish momentiga qadar kodni bajarishi mumkin. Tekshirish uchun isActive dan foydalaning yoki catch blokining tugashiga ishoning.

Xato 2: SupervisorJob ni hisobga olmasdan korutinlarni ishga tushirish

viewModelScope ichki SupervisorJob dan foydalanadi, bu xatolarni korutinlar o'rtasida izolyatsiya qiladi. Ammo viewModelScope.launch ichida o'z Job() bilan korutinani ishga tushirsangiz, bu korutina SupervisorJob ga farzand bo'ladi, lekin boshqa korutinlardagi xatolarda bekor qilishdan himoyalanmaydi.

Xato 3: Bir scope da juda ko'p korutinlar

viewModelScope qattiq chegaraga ega bo'lmasa ham, minglab faol korutinlar tizimni sekinlashtirishi mumkin. Uzun ma'lumotlar ro'yxatlari uchun har bir element uchun alohida korutina yaratish o'rniga Flow ni collectLatest bilan ishlating.

Xato 4: viewModelScope o'rniga GlobalScope dan foydalanish

Tasodifan viewModelScope o'rniga GlobalScope ni import qilsangiz, korutina ViewModel tozalanganda bekor qilinmaydi. Bu xotira oqishiga va potensial crashga olib keladi. Har doim korutinalarning viewModelScope orqali ishga tushirilganligini tekshiring, ayniqsa meros fragmentlarda.

Tez-tez beriladigan savollar

viewModelScope ning sukut bo'yicha dispetcherini o'zgartirish mumkinmi?

To'g'ridan-to'g'ri viewModelScope dispetcherini o'zgartirish mumkin emas — u qattiq Dispatchers.Main.immediate qilib o'rnatilgan. Ammo korutina ichida withContext orqali boshqa dispetcherga o'tish mumkin. Testlarda dispetcherini o'zgartirish uchun Rule orqali TestDispatcher dan foydalaning.

viewModelScope ni Repository ga qanday uzatish mumkin?

Scope ni Repository ga uzatmang — bu arxitektura prinsiplarini buzadi. Repository suspend-funksiyalar taqdim etishi kerak, ViewModel esa viewModelScope orqali korutinlarni o'zi boshqaradi. Agar Repository scope talab qilsa — arxitektura Clean Architecture foydasiga qayta ko'rib chiqing.

Nega viewModelScope SupervisorJob dan foydalanadi?

SupervisorJob bir korutinadagi istisno (masalan, bir nechta mustaqil so'rovlardan birining yuklanish xatosi) qolgan korutinlarni bekor qilmasligini kafolatlaydi. Bu turli ekranlar mustaqil ma'lumotlarni yuklaydigan ViewModel ssenariysiga mos keladi.

viewModelScope Jetpack Compose da mavjudmi?

Ha, viewModelScope UI turidan (View System yoki Jetpack Compose) qat'i nazar, har qanday ViewModel da mavjud. Compose da korutinlar ham viewModelScope orqali ishga tushiriladi, UI effektlari uchun esa LaunchedEffect va rememberCoroutineScope ishlatiladi.

viewModelScope.cancel() chaqirilganda korutinaga nima bo'ladi?

viewModelScope.cancel() chaqiruvi scope ni darhol bekor qiladi — barcha faol korutinlar CancellationException bilan tugaydi. Agar bundan keyin viewModelScope.launch ni chaqirsangiz, yangi scope getterga navbatdagi murojaatda avtomatik yaratiladi.

Xulosa

  • viewModelScope — ViewModel-ning hayotiy sikliga bog'langan va onCleared() da avtomatik bekor qilinadigan CoroutineScope
  • SupervisorJob + Dispatchers.Main — xatolarni izolyatsiyalash va UI ga xavfsiz kirishni ta'minlaydigan ichki konfiguratsiya
  • Ekran rotatsiyasi — ViewModel saqlanadi, shuning uchun viewModelScope dagi korutinlar qayta ishga tushmasdan ishlashda davom etadi
  • MVVM arxitekturasi — viewModelScope ViewModel qatlamida asinxron operatsiyalar uchun markaziy elementdir
  • lifecycleScope — ViewModel emas, Activity/Fragment hayotiy sikliga bog'liq operatsiyalar uchun alternativa
  • StateFlow — viewModelScope korutinlaridan UI ga sealed class orqali ma'lumot uzatishning afzal usuli
  • GlobalScope xavfli — viewModelScope ni GlobalScope bilan almashtirish xotira oqishiga va ilova qulashiga olib keladi

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