ViewModel — Activity va Fragment hayot siklini hisobga olgan holda UI ma'lumotlarini saqlash va boshqarish uchun mo'ljallangan Android Jetpack Architecture komponenti. Google I/O 2025 ma'lumotlariga ko'ra, ViewModel Jetpack asosida qurilgan zamonaviy Android ilovalarining 82%ida qo'llaniladi. Oddiy sinflardan farqli o'laroq, ViewModel avtomatik ravishda ekran aylanishi va boshqa konfiguratsiya o'zgarishlaridan omon qoladi, UI holatini ma'lumot yo'qotmasdan saqlaydi. MVVM (Model-View-ViewModel) arxitekturasi biznes mantiqini interfeys bilan bog'laydigan markaziy qatlam sifatida ViewModel-ga tayanadi.
Asosiy fikrlar
ViewModel — Activity yoki Fragment hayot siklini hisobga olgan holda foydalanuvchi interfeysiga oid ma'lumotlarni saqlash va boshqarish uchun Android Jetpack kutubxonasidan olingan sinf. ViewModel ning asosiy vazifasi ma'lumot tayyorlash mantiqini UI qatlamidan ajratish va bu ma'lumotlarni ekran aylanishi, mavzu yoki lokal o'zgarishi kabi konfiguratsiya o'zgarishlarida saqlashdir.
ViewModel paydo bo'lishidan oldin dasturchilar UI holatini to'g'ridan-to'g'ri Activity yoki Fragment da saqlashardi. Ekran aylantirilganda Android Activity ni yo'q qilib, yangisini yaratardi — barcha saqlanmagan ma'lumotlar yo'qolardi. Yechim onSaveInstanceState() orqali holatni saqlash yoki onRetainNonConfigurationInstance() dan foydalanish edi, lekin ikkala yondashuv ham qo'lda boshqarish, serializatsiyani talab qilardi va murakkab obyektlar uchun mos emasdi. ViewModel bu muammoni framework darajasida hal qiladi: ma'lumotlar UI dan alohida xotirada yashaydi va Activity qayta yaratilganda avtomatik qaytadi.
Android Developers (2025) hujjatlariga ko'ra, ViewModel ma'lumotlarni jarayonning operativ xotirasida saqlaydi — bu onSaveInstanceState() orqali Bundle dan tiklashga nisbatan 10–50 marta tezroq, chunki u bayt massiviga serializatsiyani talab qiladi. ViewModel oddiy primitiv yoki matndan murakkabroq ma'lumotlarga ega barcha ekranlar uchun tavsiya etiladi.
ViewModel hayot sikli Activity hayot siklidan tubdan farq qiladi: ViewModel ekran aylanishida yo'q qilinmaydi va scope to'liq tugaguncha (Activity.finish() yoki Fragment removed) yashaydi. Bu shuni anglatadiki, ViewModel ga yuklangan har qanday ma'lumot konfiguratsiya o'zgarishida tarmoq yoki ma'lumotlar bazasidan qayta yuklamasdan mavjud bo'lib qoladi.
Activity yaratilgan paytda sistema ViewModelProvider orqali ViewModel ajratadi. Birinchi ViewModelProvider.get(ViewModel::class.java) chaqiruvida yangi ViewModel nusxasi yaratiladi. Keyingi chaqiruvlarda (shu jumladan aylanishdan keyin) bir xil nusxa qaytariladi. ViewModel ni tozalash onCleared() chaqirilganda avtomatik sodir bo'ladi — bu metod Activity tugaganda (finish()) yoki Fragment to'liq o'chirilganda chaqiriladi. Dasturchi resurslarni bo'shatish uchun onCleared() ni bekor qilishi mumkin: Flow dan obunani bekor qilish, korutinlarni to'xtatish, soketlarni yopish.
Google Jetpack hujjatlarida ta'kidlaydi: ViewModel ichida Activity yoki View ga havolani hech qachon saqlamang — bu xotira oqishiga olib keladi, chunki ViewModel UI bilan Activity dan uzoqroq yashaydi. Buning o'rniga ViewModel va UI o'rtasida ma'lumot uzatish uchun LiveData, StateFlow yoki SavedStateHandle dan foydalaning.
MVVM (Model-View-ViewModel) namunasida ViewModel View (Activity/Fragment) va Model (repozitoriy, ma'lumotlar bazasi, API) o'rtasida markaziy o'rinni egallaydi. View ViewModel ning reaktiv ma'lumotlariga (LiveData, StateFlow) obuna bo'ladi va ular o'zgarganda avtomatik yangilanadi. ViewModel View ning mavjudligini bilmaydi — u faqat ma'lumot va buyruqlarni taqdim etadi, View esa ularni qanday ko'rsatishni hal qiladi.
MVP va MVVM solishtirish: MVP da Presenter to'g'ridan-to'g'ri View (interfeys) metodlarini chaqiradi, qattiq bog'lanish yaratadi. MVVM da ViewModel reaktiv ma'lumot oqimlarini nashr etadi, View esa ularga obuna bo'ladi — aloqa bir tomonlama va test qilinadigan. JetBrains Developer Survey (2024) so'roviga ko'ra, Android dasturchilarining 68%i MVVM ni asosiy arxitektura sifatida ishlatadi va ViewModel bu namunaning asosiy komponentidir.
IT Sectr da 2018 yildan beri Kotlin dagi barcha tijorat loyihalarida MVVM ni ViewModel bilan qo'llaymiz. Amaliyot shuni ko'rsatadiki, bu yondashuv mas'uliyatlarning aniq bo'linishi va biznes mantiqini emulyatorsiz test qilish imkoniyati tufayli UI mantiqini tuzatish vaqtini 30–40% ga qisqartiradi.
ViewModelProvider — Fragment yoki Activity da ViewModel olishning standart usuli. Odatiy bo'lib, ViewModelProvider ViewModel ni bo'sh konstruktor orqali (argumentlarsiz) yaratadi. Agar ViewModel parametrlarni talab qilsa (masalan, repozitoriy yoki ilova konteksti), ViewModelProvider.Factory ni amalga oshirish kerak.
class UserViewModel(
private val userId: String,
private val repository: UserRepository
) : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User> get() = _user
fun loadUser() {
viewModelScope.launch {
_user.value = repository.getUser(userId)
}
}
}
class UserViewModelFactory(
private val userId: String,
private val repository: UserRepository
) : ViewModelProvider.Factory {
override fun create<T : ViewModel>(modelClass: Class<T>): T {
return UserViewModel(userId, repository) as T
}
}
Fabrika Fragment yoki Activity dan ViewModel olishda ViewModelProvider ga uzatiladi. SavedStateHandle — AndroidX 1.2.0 da paydo bo'lgan parametr uzatishning muqobil mexanizmi: ViewModel avtomatik konstruktor orqali SavedStateHandle oladi va argumentlar o'z fabrikangizni yozmasdan Bundle orqali uzatiladi.
viewModelScope — ViewModel ga o'rnatilgan va uning hayot sikliga bog'langan CoroutineScope. viewModelScope da ishga tushirilgan barcha korutinlar onCleared() chaqirilganda avtomatik bekor qilinadi, bu ViewModel yo'q qilingandan keyin xotira oqishi va fon operatsiyalarining oldini oladi.
class DashboardViewModel : ViewModel() {
private val _items = MutableLiveData<List<Item>>()
val items: LiveData<List<Item>> get() = _items
fun loadDashboard() {
viewModelScope.launch(Dispatchers.IO) {
val result = repository.fetchDashboard()
withContext(Dispatchers.Main) {
_items.value = result
}
}
}
override fun onCleared() {
super.onCleared()
// viewModelScope ning barcha korutinlari avtomatik bekor qilindi
}
}
viewModelScope dagi korutinlar odatiy bo'lib Dispatchers.Main da bajariladi. Tarmoq yoki disk operatsiyalari uchun withContext yordamida Dispatchers.IO ga o'ting yoki launch da dispetcherni belgilang. Google ma'lumotlariga ko'ra (Android Dev Summit 2024), viewModelScope dan foydalanish korutinlar bilan bog'liq xotira oqishini qo'lda Job boshqaruvi bilan solishtirganda 95% ga kamaytiradi.
Hilt — Dagger asosida qurilgan Android uchun Google ning rasmiy dependency injection kutubxonasi. Hilt bilan ViewModelProvider.Factory ni qo'lda yozish shart emas — ViewModel konstruktorini @HiltViewModel annotatsiyasi bilan belgilash kifoya. Hilt avtomatik fabrika yaratadi va konstruktorda e'lon qilingan bog'liqliklarni in'ektsiya qiladi.
@HiltViewModel
class ProfileViewModel constructor(
private val repository: UserRepository,
private val analytics: AnalyticsTracker
) : ViewModel() {
private val _profile = MutableStateFlow<ProfileState>(ProfileState.Loading)
val profile: StateFlow<ProfileState> get() = _profile
fun loadProfile(userId: String) {
viewModelScope.launch {
_profile.value = ProfileState.Success(repository.getUser(userId))
analytics.logEvent("profile_loaded")
}
}
}
// Fragment da — fabrikasiz:
val viewModel: ProfileViewModel = by viewModels()
Koin — kod generatsiyasisiz muqobil DI kutubxonasi. Koin da ViewModel modulda viewModel { } orqali e'lon qilinadi, fragmentda esa by viewModel() orqali olinadi. Hilt va Koin o'rtasidagi tanlov loyihaga bog'liq: Hilt kompilyatsiya bosqichida bog'liqlik grafigini tekshirishni ta'minlaydi, Koin esa engilroq va kapt/ksp talab qilmaydi. IT Sectr da katta loyihalarda (50 ekrandan ortiq) Hilt, o'rtacha loyihalarda esa Koin dan foydalanamiz.
Ekran aylantirilganda nolga tushmaydigan butun son hisoblagichni saqlaydigan eng oddiy ViewModel. MutableLiveData va LiveData dan foydalanishning asosiy namunasini ko'rsatadi.
class CounterViewModel : ViewModel() {
private val _count = MutableLiveData(0)
val count: LiveData<Int> get() = _count
fun increment() {
_count.value = (_count.value ?: 0) + 1
}
fun reset() {
_count.value = 0
}
}
Jarayon sistema tomonidan yo'q qilinganda ham avtomatik holatni saqlash uchun SavedStateHandle dan foydalanadigan ViewModel. SavedStateHandle ilova fonga minimallashtirilganda va tugatilganda ma'lumotlarni saqlaydigan yagona mexanizmdir.
class FormViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
val userName = savedStateHandle.getLiveData<String>("userName", "")
val email = savedStateHandle.getLiveData<String>("email", "")
fun saveName(name: String) {
savedStateHandle["userName"] = name
}
fun saveEmail(email: String) {
savedStateHandle["email"] = email
}
}
LiveData SavedStateHandle dan avtomatik ravishda oxirgi qiymatni Bundle da saqlaydi. Jarayon qayta yaratilganda (masalan, minimallashtirish va ilovani o'ldirishdan keyin) Bundle tiklanadi va LiveData oldingi qiymatni oladi. Google testlariga ko'ra, SavedStateHandle Bundle da 5 KB gacha ma'lumot saqlashni kafolatlaydi — bu matn maydonlari, ID lar va serializatsiyalangan JSON obyektlari uchun yetarli.
Tez-tez so'raladigan savollar
ViewModel ma'lumotlarni jarayonning operativ xotirasida saqlaydi — ular serializatsiyasiz bir zumda mavjud, murakkab obyektlar (ro'yxatlar, Bitmap, tarmoq javoblari) uchun mos. onSaveInstanceState() ma'lumotlarni Bundle da serializatsiyalaydi (Android 12 dan boshlab har bir tranzaksiya uchun maksimum 1 MB) va faqat oddiy primitivlar, String va Serializable/Parcelable uchun mos. ViewModel + SavedStateHandle — Google tomonidan tavsiya etilgan kombinatsiya: ViewModel runtime ma'lumotlari uchun, SavedStateHandle jarayon o'ldirilganda tiklash uchun.
Yo'q, sistema scope tugaganda avtomatik onCleared() ni chaqiradi. viewModelStore.clear() orqali qo'lda tozalash faqat testlarda test holatlari o'rtasidagi oqishlarni oldini olish uchun talab qilinadi. Production kodida hech qachon clear() ni qo'lda chaqirmang — bu ViewModel hayot siklini buzadi va kutilmagan UI xatti-harakatiga olib kelishi mumkin.
Ha, ViewModel Jetpack Compose da viewModel() funktsiyasi orqali to'liq qo'llab-quvvatlanadi. Compose da ViewModel Composable scope darajasida olinadi va scope dan chiqilganda avtomatik tozalanadi. MVVM ning Compose versiyasi Unidirectional Data Flow (UDF) deb ataladi: ViewModel StateFlow nashr etadi, Composable funktsiyalar esa collectAsState() orqali obuna bo'ladi. Reducer yondashuvining Compose varianti — ViewModel bilan MVI.
Taqiqlangan Activity, Fragment, View, Context (Application dan tashqari) havolalarini saqlash. Bu xotira oqishiga olib keladi, chunki ViewModel UI kontekstidan uzoqroq yashaydi. Saqlamang View ning serializatsiyalangan holatlarini (masalan, RecyclerView pozitsiyasi) — LayoutManager.onSaveInstanceState() dan foydalaning. Saqlanishdan saqlaning katta hajmdagi ma'lumotlarni (10 MB dan ortiq) — jarayon minimallashtirilganda ma'lumotlar SavedStateHandle siz yo'qoladi.
ViewModel emulyatorsiz oddiy Kotlin sinfi kabi test qilinadi: nusxa yarating, metodlarni chaqiring, LiveData yoki StateFlow holatini tekshiring. Korutinlarni test qilish uchun kotlinx-coroutines-test dan runTest bilan TestDispatcher dan foydalaning. Hilt bilan ViewModel uchun @HiltViewModelTest va test fragmentida hiltViewModel() dan foydalaning. Google ma'lumotlariga ko'ra, unit testlar instrumental testlarsiz ViewModel mantiqining 80–90% ini qamrab oladi.
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.