ViewModel — bu nədir, Android Jetpack-də UI məlumatlarının idarə edilməsi

Müəllif: IT Sectr Dərc olunub: 2026-02-19 Oxuma vaxtı: 9 dəq

ViewModel — Activity və Fragment-in həyat dövrü nəzərə alınmaqla UI məlumatlarını saxlamaq və idarə etmək üçün nəzərdə tutulmuş Android Jetpack Architecture komponenti. Google I/O 2025 məlumatına görə, ViewModel Jetpack üzərində qurulmuş müasir Android tətbiqlərinin 82%-də istifadə olunur. Adi siniflərdən fərqli olaraq, ViewModel avtomatik olaraq ekranın döndərilməsi və digər konfiqurasiya dəyişikliklərindən sağ çıxır, UI vəziyyətini məlumat itkisi olmadan qoruyur. MVVM (Model-View-ViewModel) arxitekturası biznes məntiqini interfeyslə birləşdirən mərkəzi təbəqə kimi ViewModel-ə əsaslanır.

Əsas məqamlar

  • ViewModel — UI məlumatlarını saxlamaq üçün Jetpack komponenti, ekran döndərməyə və Activity-nin yenidən yaradılmasına davamlıdır.
  • ViewModel-in həyat dövrü ayrıca Activity nümunəsinə deyil, scope-a (Activity/Fragment/Composable) bağlıdır.
  • viewModelScope — ViewModel daxilində quraşdırılmış korutin, ViewModel təmizləndikdə avtomatik ləğv edilir.
  • ViewModelProvider — Hilt və ya Koin vasitəsilə dependency injection dəstəyi ilə ViewModel yaratmaq üçün fabrik.
  • MVVM-də ViewModel MVP-dəki presenteri əvəz edir, LiveData və ya StateFlow vasitəsilə konkret View-ə bağlanmadan azad edir.

Android-də ViewModel nədir?

ViewModel — Activity və ya Fragment-in həyat dövrü nəzərə alınmaqla istifadəçi interfeysi ilə əlaqəli məlumatları saxlamaq və idarə etmək üçün Android Jetpack kitabxanasından olan sinifdir. ViewModel-in əsas vəzifəsi məlumat hazırlığı məntiqini UI təbəqəsindən ayırmaq və bu məlumatları ekran döndərmə, mövzu və ya lokal dəyişikliyi kimi konfiqurasiya dəyişikliklərində qorumaqdır.

ViewModel ortaya çıxmazdan əvvəl tərtibatçılar UI vəziyyətini birbaşa Activity və ya Fragment-də saxlayırdılar. Ekran döndərildikdə Android Activity-ni məhv edir və yenisini yaradırdı — bütün saxlanılmamış məlumatlar itirdi. Həll yolu onSaveInstanceState() vasitəsilə vəziyyəti saxlamaq və ya onRetainNonConfigurationInstance() istifadə etmək idi, lakin hər iki yanaşma əl ilə idarəetmə, serializasiya tələb edirdi və mürəkkəb obyektlər üçün uyğun deyildi. ViewModel bu problemi framework səviyyəsində həll edir: məlumatlar UI-dan ayrı olaraq yaddaşda yaşayır və Activity yenidən yaradıldıqda avtomatik qayıdır.

Android Developers (2025) sənədləşməsinə görə, ViewModel məlumatları prosesin operativ yaddaşında saxlayır — bu, serializasiya tələb edən onSaveInstanceState() vasitəsilə Bundle-dən bərpadan 10–50 dəfə sürətlidir. ViewModel sadə primitiv və ya sətirdən daha mürəkkəb məlumatları olan bütün ekranlar üçün tövsiyə olunur.

ViewModel-in həyat dövrü: Activity-dən nə ilə fərqlənir

ViewModel-in həyat dövrü Activity-nin həyat dövründən prinsipial olaraq fərqlənir: ViewModel ekran döndərildikdə məhv edilmir və scope-un tamamilə bitməsinə qədər (Activity.finish() və ya Fragment removed) yaşayır. Bu o deməkdir ki, ViewModel-ə yüklənmiş istənilən məlumat konfiqurasiya dəyişikliyində şəbəkədən və ya verilənlər bazasından yenidən yükləmədən əlçatan qalır.

Activity yaradıldığı anda sistem ViewModelProvider vasitəsilə ViewModel ayırır. ViewModelProvider.get(ViewModel::class.java) ilk çağırışda yeni ViewModel nümunəsi yaradılır. Təkrar çağırışlarda (o cümlədən dönmədən sonra) eyni nümunə qaytarılır. ViewModel-in təmizlənməsi onCleared() çağırıldıqda avtomatik baş verir — bu metod Activity finişləndikdə (finish()) və ya Fragment tam silindikdə çağırılır. Tərtibatçı resursları azad etmək üçün onCleared()-ı ləğv edə bilər: Flow-dan abunəni ləğv etmək, korutinləri dayandırmaq, soketləri bağlamaq.

Google Jetpack sənədləşməsində vurğulayır: ViewModel daxilində Activity və ya View-ə istinadı heç vaxt saxlamayın — bu, yaddaş sızmasına gətirib çıxarır, çünki ViewModel UI ilə Activity-dən daha uzun yaşayır. Bunun əvəzinə ViewModel və UI arasında məlumat ötürmək üçün LiveData, StateFlow və ya SavedStateHandle istifadə edin.

MVVM arxitekturasında ViewModel

MVVM (Model-View-ViewModel) nümunəsində ViewModel View (Activity/Fragment) və Model (repozitori, verilənlər bazası, API) arasında mərkəzi yer tutur. View ViewModel-in reaktiv məlumatlarına (LiveData, StateFlow) abunə olur və onlar dəyişdikdə avtomatik yenilənir. ViewModel View-in mövcudluğundan xəbərsizdir — o, yalnız məlumat və əmrlər təqdim edir, View isə onları necə göstərəcəyinə qərar verir.

MVP və MVVM müqayisəsi: MVP-də Presenter birbaşa View (interfeys) metodlarını çağırır, sıx əlaqə yaradır. MVVM-də ViewModel reaktiv məlumat axınları yayımlayır, View isə onlara abunə olur — əlaqə birtərəfli və test edilə biləndir. JetBrains Developer Survey (2024) sorğusuna görə, Android tərtibatçılarının 68%-i MVVM-dən əsas arxitektura kimi istifadə edir və ViewModel bu nümunənin əsas komponentidir.

IT Sectr-də 2018-ci ildən Kotlin-dəki bütün kommersiya layihələrində MVVM-ni ViewModel ilə tətbiq edirik. Təcrübə göstərir ki, bu yanaşma məsuliyyətlərin aydın bölünməsi və biznes məntiqinin emulyator olmadan test edilə bilməsi sayəsində UI məntiqinin sazlanması vaxtını 30–40% azaldır.

ViewModelProvider və fabriklər: parametrlərlə yaratma

ViewModelProvider — Fragment və ya Activity-də ViewModel əldə etməyin standart üsulu. Susmaya görə, ViewModelProvider ViewModel-i boş konstruktor vasitəsilə (arqumentsiz) yaradır. ViewModel parametrlər tələb edirsə (məsələn, repozitori və ya tətbiq konteksti), ViewModelProvider.Factory tətbiq etmək lazımdır.

kotlin
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
    }
}

Fabrik Fragment və ya Activity-dən ViewModel əldə edərkən ViewModelProvider-a ötürülür. SavedStateHandle — AndroidX 1.2.0-da ortaya çıxmış alternativ parametr ötürmə mexanizmi: ViewModel avtomatik olaraq konstruktor vasitəsilə SavedStateHandle alır və arqumentlər öz fabrikinizi yazmadan Bundle vasitəsilə ötürülür.

viewModelScope və ViewModel-də korutinlər

viewModelScope — ViewModel-ə quraşdırılmış və onun həyat dövrünə bağlı CoroutineScope-dur. viewModelScope-da işə salınmış bütün korutinlər onCleared() çağırıldıqda avtomatik ləğv edilir ki, bu da ViewModel məhv edildikdən sonra yaddaş sızmalarının və fon əməliyyatlarının qarşısını alır.

kotlin
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-un bütün korutinləri avtomatik ləğv edilir
    }
}

viewModelScope-dəki korutinlər susmaya görə Dispatchers.Main-də icra olunur. Şəbəkə və ya disk əməliyyatları üçün withContext istifadə edərək Dispatchers.IO-ya keçin və ya launch-da dispetçer təyin edin. Google-ə görə (Android Dev Summit 2024), viewModelScope istifadəsi korutinlərlə bağlı yaddaş sızmalarını əl ilə Job idarəsi ilə müqayisədə 95% azaldır.

Hilt və Koin ilə ViewModel: DI yanaşmaları

Hilt — Dagger üzərində qurulmuş Android üçün Google-dan rəsmi dependency injection kitabxanası. Hilt ilə ViewModelProvider.Factory əl ilə yazmaq lazım deyil — ViewModel konstruktorunu @HiltViewModel annotasiyası ilə qeyd etmək kifayətdir. Hilt avtomatik fabrik yaradır və konstruktorda bəyan edilmiş asılılıqları injection edir.

kotlin
@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-də — fabrik olmadan:
val viewModel: ProfileViewModel = by viewModels()

Koin — kod generasiyası olmayan alternativ DI kitabxanası. Koin-də ViewModel modulda viewModel { } vasitəsilə bəyan edilir, fragmentdə isə by viewModel() ilə əldə edilir. Hilt və Koin arasında seçim layihədən asılıdır: Hilt kompilyasiya mərhələsində asılılıq qrafının yoxlanmasını təmin edir, Koin isə daha yüngüldür və kapt/ksp tələb etmir. IT Sectr-də böyük layihələrdə (50 ekrandan çox) Hilt, orta layihələrdə isə Koin istifadə edirik.

Kod nümunələri: Kotlin-də ViewModel

Nümunə 1: Sayğac ilə əsas ViewModel

Ekran döndərildikdə sıfırlanmayan tam sayğac saxlayan ən sadə ViewModel. MutableLiveData və LiveData-dan istifadənin əsas nümunəsini göstərir.

kotlin
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
    }
}

Nümunə 2: SavedStateHandle ilə ViewModel

Proses sistem tərəfindən məhv edildikdə belə avtomatik vəziyyət saxlamaq üçün SavedStateHandle istifadə edən ViewModel. SavedStateHandle tətbiq fonda minimuma endirildikdə və dayandırıldıqda məlumatları qoruyan yeganə mexanizmdir.

kotlin
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 olaraq son dəyəri Bundle-də saxlayır. Proses yenidən yaradıldıqda (məsələn, minimuma endirmə və tətbiqin öldürülməsindən sonra) Bundle bərpa olunur və LiveData əvvəlki dəyəri alır. Google testlərinə görə, SavedStateHandle Bundle-də 5 KB-a qədər məlumatın saxlanmasını təmin edir — bu, mətn sahələri, ID-lər və serializə edilmiş JSON obyektləri üçün kifayətdir.

Tez-tez verilən suallar

ViewModel onSaveInstanceState-dən nə ilə fərqlənir?

ViewModel məlumatları prosesin operativ yaddaşında saxlayır — onlar serializasiya olmadan dərhal əlçatandır, mürəkkəb obyektlər (siyahılar, Bitmap, şəbəkə cavabları) üçün uyğundur. onSaveInstanceState() məlumatları Bundle-də serializasiya edir (Android 12-dən başlayaraq hər əməliyyat üçün maksimum 1 MB) və yalnız sadə primitivlər, String və Serializable/Parcelable üçün uyğundur. ViewModel + SavedStateHandle — Google tərəfindən tövsiyə olunan kombinasiya: ViewModel runtime məlumatları üçün, SavedStateHandle proses öldürüldükdə bərpa üçün.

ViewModel-i əl ilə təmizləmək lazımdırmı?

Xeyr, sistem scope bitdikdə avtomatik olaraq onCleared() çağırır. viewModelStore.clear() vasitəsilə əl ilə təmizləmə yalnız testlər arasında sızmaların qarşısını almaq üçün testlərdə tələb olunur. Production kodunda heç vaxt clear()-ı əl ilə çağırmayın — bu, ViewModel-in həyat dövrünü pozur və gözlənilməz UI davranışına səbəb ola bilər.

ViewModel Compose-da istifadə oluna bilərmi?

Bəli, ViewModel Jetpack Compose-da viewModel() funksiyası vasitəsilə tam dəstəklənir. Compose-da ViewModel Composable scope səviyyəsində əldə edilir və scope-dan çıxıldıqda avtomatik təmizlənir. MVVM-in Compose versiyası Unidirectional Data Flow (UDF) adlanır: ViewModel StateFlow yayımlayır, Composable funksiyalar isə collectAsState() vasitəsilə abunə olur. Reducer yanaşmasının Compose variantı — ViewModel ilə MVI.

ViewModel-də nə saxlamaq qadağandır?

Qadağandır Activity, Fragment, View, Context (Application istisna olmaqla) istinadlarını saxlamaq. Bu, yaddaş sızmasına gətirib çıxarır, çünki ViewModel UI kontekstindən daha uzun yaşayır. Saxlamayın View-in serializə edilmiş vəziyyətlərini (məsələn, RecyclerView mövqeyi) — LayoutManager.onSaveInstanceState() istifadə edin. Çəkinin böyük həcmdə məlumat saxlamaqdan (10 MB-dan çox) — proses minimuma endirildikdə məlumatlar SavedStateHandle olmadan itiriləcək.

ViewModel-i necə test etməli?

ViewModel emulyator olmadan adi Kotlin sinfi kimi test edilir: nümunə yaradırsınız, metodları çağırırsınız, LiveData və ya StateFlow vəziyyətini yoxlayırsınız. Korutinləri test etmək üçün kotlinx-coroutines-test-dən runTest ilə TestDispatcher istifadə edin. Hilt ilə ViewModel üçün @HiltViewModelTest və test fragmentində hiltViewModel() istifadə edin. Google məlumatına görə, vahid testlər instrumental testlər olmadan ViewModel məntiqinin 80–90%-ni əhatə edir.

Nəticə

  • ViewModel — UI məlumatlarını saxlamaq üçün Jetpack komponenti, vəziyyət itkisi olmadan konfiqurasiya dəyişikliklərindən sağ çıxır.
  • ViewModel-in həyat dövrü scope-a (Activity/Fragment) bağlıdır, Activity nümunəsinə deyil — təmizləmə scope bitdikdə baş verir.
  • ViewModelProvider — ViewModel yaratmaq üçün fabrik metodu; parametrlər üçün ViewModelProvider.Factory tətbiq edilir.
  • viewModelScope — quraşdırılmış CoroutineScope, onCleared() zamanı korutinləri avtomatik ləğv edir, yaddaş sızmalarını aradan qaldırır.
  • SavedStateHandle — proses öldürüldükdə vəziyyəti saxlamaq mexanizmi, ViewModel konstruktoruna inteqrasiya olunur.
  • Hilt və @HiltViewModel — böyük layihələrdə ViewModel üçün standart DI üsulu; Koin — kod generasiyası olmayan yüngül alternativ.
  • ViewModel — MVVM və UDF arxitekturalarının əsası, Google I/O 2025-ə görə Jetpack tətbiqlərinin 82%-də istifadə olunur.

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.

Layihəni müzakirə et

Həm də oxuyun