MVVM: bu nima, Model-View-ViewModel patterni mobil ishlanmada

Muallif: IT Sectr Nashr etilgan: 2026-02-16 O'qish vaqti: 9 daq

MVVM (Model-View-ViewModel) — ViewModel Presenter o'rnini egallaydigan va View bilan aloqa qilish uchun reaktiv mexanizmlardan foydalanadigan arxitektura patternidir: SwiftUI-da ObservableObject, Android-da LiveData/StateFlow. ViewModel View-ga havolaga ega emas — ma'lumotlar obuna orqali uzatiladi, bu ViewContract interfeyslariga bo'lgan ehtiyojni yo'q qiladi va testlashni yanada osonlashtiradi. Apple 2019-yildan SwiftUI bilan MVVM-ni, Google esa Jetpack bilan MVVM-ni Android-ning rasmiy arxitekturasi sifatida tavsiya qiladi. Batafsil Android Architecture Guide-da.

Asosiy

  • MVVM — Model (ma'lumotlar), View (interfeys), ViewModel (View-ga havolasiz holat va mantiq)
  • Reactive binding — LiveData, StateFlow, ObservableObject ma'lumot o'zgarganda UI-ni avtomatik yangilaydi
  • ViewModel — ekran aylanishidan omon qoladi va Android SDK/UIKit-ga bog'liq emas, unit-testlar bilan tekshiriladi
  • Android Jetpack — ViewModel, LiveData, DataBinding — Google-dan MVVM uchun rasmiy stack
  • SwiftUI + Combine — iOS-da @Published va @ObservedObject bilan MVVM-ning mahalliy tatbiqi

MVVM nima: Model-View-ViewModel patternining mohiyati

MVVM (Model-View-ViewModel) — 2005-yilda John Gossman tomonidan Microsoft-ning Windows Presentation Foundation (WPF) uchun tasvirlangan arxitektura patternidir. ViewModel — ekran holati va biznes mantiqini o'z ichiga olgan, ammo View-ga havolasi bo'lmagan markaziy komponentdir. Ma'lumotlar reaktiv bog'lash mexanizmlari orqali uzatiladi: View ViewModel o'zgarishlariga obuna bo'ladi va ma'lumotlar o'zgarganda avtomatik ravishda qayta chiziladi.

MVVM va MVP o'rtasidagi asosiy farq — ViewContract yo'qligi. MVP-da Presenter view.showUser(data) usullarini chaqiradi, ya'ni Presenter faol ravishda ma'lumotlarni View-ga “itaradi”. MVVM-da View o'zi ma'lumotlarni ViewModel-dan obuna orqali “toradi”: ViewModel obunachisi bor-yo'qligini bilmaydi. Bu ajratilgan View muammosini bartaraf qiladi — agar Activity aylanish vaqtida yo'q qilinsa, ViewModel ishni davom ettiradi, yangi Activity esa shunchaki dolzarb ma'lumotlarga obuna bo'ladi. IT Sectr-da 2020-yildan beri barcha yangi loyihalarda MVVM-dan foydalanamiz — kod oldindan taxmin qilinadigan, testlar barqaror bo'ldi.

KomponentMas'uliyatPlatforma
ModelMa'lumotlar, biznes mantiq, repozitoriylarAndroid/iOS
ViewKo'rsatish, ViewModel-ga obunaActivity/Composable, UIView/SwiftUI View
ViewModelEkran holati, mantiq, navigatsiyaViewModel (Jetpack), ObservableObject

Reaktiv bog'lash — MVVM-ning asosi. Android-da LiveData (Jetpack qismi) kuzatiladigan ma'lumot omboridir. Activity observe() orqali obuna bo'ladi: viewModel.user.observe(this) { user -> binding.name.text = user.name }. user o'zgarganda barcha obunachilar avtomatik ravishda yangi qiymatni oladi. iOS-da SwiftUI ViewModel-da @Published xususiyatlaridan foydalanadi — o'zgarishlar avtomatik ravishda View-ni qayta chizadi. Bu MVP-da talab qilinadigan qo'lda showUser/hideLoading chaqiruvlarini yo'q qiladi.

Android-da MVVM: ViewModel, LiveData va StateFlow

Jetpack-dan ViewModel — Google-dan MVVM-ni tatbiq qilish uchun rasmiy komponent. ViewModel ekran aylanishidan omon qoladi: konfiguratsiya o'zgarganda Activity yo'q qilinadi va qayta yaratiladi, ViewModel esa xotirada qoladi. Activity-ning yangi namunasi ViewModelProvider orqali bir xil ViewModel-ni oladi. ViewModel Activity, Context yoki View-ga havolaga ega emas — u toza va Robolectric holda unit-testlar bilan tekshiriladi.

kotlin
// ViewModel StateFlow bilan — MVVM-ning zamonaviy tatbiqi
class UserViewModel(
    private val repository: UserRepository
) : ViewModel() {

    private val _state = MutableStateFlow<UserState>(UserState.Loading)
    val state: StateFlow<UserState> = _state.asStateFlow()

    fun loadUser(userId: Int) {
        viewModelScope.launch {
            _state.value = UserState.Loading
            repository.getUser(userId)
                .onSuccess { user ->
                    _state.value = UserState.Success(user)
                }
                .onFailure { e ->
                    _state.value = UserState.Error(e.message ?: "Unknown")
                }
        }
    }
}

sealed interface UserState {
    data object Loading : UserState
    data class Success(val user: User) : UserState
    data class Error(val message: String) : UserState
}

// View (Activity) state-ga obuna bo'ladi
class UserActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.state.onEach { state ->
            when (state) {
                is UserState.Loading -> /* yuklashni ko'rsatish */
                is UserState.Success -> /* ma'lumotlarni ko'rsatish */
                is UserState.Error -> /* xatoni ko'rsatish */
            }
        }.launchIn(lifecycleScope)
        viewModel.loadUser(42)
    }
}

LiveData vs StateFlow — LiveData (2017) — Activity hayot aylanishi uchun optimallashtirilgan birinchi Jetpack reaktiv komponenti: onStop-da avtomatik obunani bekor qilish. StateFlow (2021) — hayot aylanishiga bog'liq bo'lmagan, ammo lifecycleScope orqali qo'lda obunani bekor qilishni talab qiladigan Kotlin Flow tatbiqi. StateFlow coroutines, concat, map va LiveData-da mavjud bo'lmagan boshqa Flow operatorlarini qo'llab-quvvatlaydi. IT Sectr-da barcha yangi ViewModel-lar uchun StateFlow-dan foydalanamiz — u qisqaroq, kuchliroq va korutinlar bilan yaxshiroq integratsiyalashadi.

DataBinding va ViewBinding — DataBinding ViewModel-ni XML bilan @{viewModel.user.name} orqali to'g'ridan-to'g'ri layoutda bog'laydi, Activity-dagi kodni yo'q qiladi. ViewBinding View-ga kirish uchun tip-xavfsiz sinf yaratadi. Google oddiy loyihalar uchun ViewBinding, murakkab ma'lumot bog'lashi bo'lgan loyihalar uchun DataBinding tavsiya qiladi. Jetpack Compose-da DataBinding kerak emas — @Composable funksiyalari State o'zgarganda avtomatik qayta chiziladi.

iOS-da MVVM: ObservableObject va SwiftUI

iOS-da MVVM Combine-dan ObservableObject orqali tatbiq qilinadi. ViewModel — ObservableObject-dan meros oladigan sinf, @Published maydonlari bilan. SwiftUI View @ObservedObject yoki @StateObject orqali ViewModel-ga obuna bo'ladi. @Published xususiyati o'zgarganda SwiftUI ushbu xususiyatga bog'liq bo'lgan View-ni avtomatik qayta chizadi. Apple SwiftUI-ni 2019-yilda WWDC-da Combine bilan birga taqdim etdi — shu paytdan boshlab MVVM iOS uchun rasman tavsiya etilgan pattern bo'ldi.

swift
import SwiftUI
import Combine

// ViewModel — @Published maydonlari bilan ObservableObject
final class UserViewModel: ObservableObject {
    @Published private(set) var state: UserState = .loading
    private let service: UserService

    init(service: UserService) {
        self.service = service
    }

    func loadUser(id: Int) {
        state = .loading
        service.fetchUser(id: id) { [weak self] result in
            guard let self else { return }
            switch result {
            case .success(let user):
                self.state = .success(user)
            case .failure(let error):
                self.state = .error(error.localizedDescription)
            }
        }
    }
}

enum UserState {
    case loading
    case success(User)
    case error(String)
}

// SwiftUI View — ViewModel-ga obuna bo'ladi
struct UserView: View {
    @StateObject private var viewModel: UserViewModel

    var body: some View {
        switch viewModel.state {
        case .loading:
            ProgressView()
        case .success(let user):
            VStack {
                Text(user.name).font(.title)
                Text(user.email).font(.body)
            }
        case .error(let message):
            Text(message).foregroundColor(.red)
        }
    }
}

@StateObject vs @ObservedObject — @StateObject ViewModel yaratadi va uning hayot aylanishini boshqaradi (View hayoti davomida bir marta). @ObservedObject — ViewModel tashqarida yaratiladi va View-ga uzatiladi. WWDC 2022 yaratish uchun @StateObject va ViewModel-ni Views o'rtasida uzatish uchun @ObservedObject tavsiya qiladi. iOS 17 (2023) da @Observable paydo bo'ldi — obunani avtomatlashtiradigan va @Published annotatsiyalarini yo'q qiladigan makro. @Observable — Combine evolyutsiyasi bo'lib, iOS ishlanmasini Kotlin Flow reaktivligiga yaqinlashtiradi.

UIKit + MVVM — UIKit-da (SwiftUI holda) loyihalar uchun MVVM Combine va @Published orqali UIViewController-da sink() bilan obuna bo'lib tatbiq qilinadi. ViewModel bir xil, View — @Published-ga obuna bo'lgan UIViewController. Combine iOS 13 (2019) dan boshlab mavjud va tizimga o'rnatilgan — qo'shimcha bog'liqliklarni talab qilmaydi. Apple Developer Survey (2025) ma'lumotiga ko'ra, iOS loyihalarining 45% hatto UIKit-da Combine-dan foydalanadi, 35% SwiftUI + Combine-dan foydalanadi, 20% — RxSwift (legacy).

MVVM va MVP solishtiruvi: afzalliklari va kamchiliklari

MVVM MVP-dan ustun uchta asosiy jihatda: ViewContract interfeyslarining yo'qligi, obunalarni avtomatik boshqarish va ekran aylanishidan omon qolish. MVP-da har bir ekran ViewContract interfeysi + Presenter sinfi + onStart/onStop-da obuna/obunani bekor qilishni talab qiladi. MVVM-da faqat ViewModel yaratiladi — Activity-da obuna observe() orqali qo'lda detach() holda amalga oshiriladi.

MezonMVPMVVM
ViewContract interfeyslari1 ekrangaKerak emas
Obuna boshqaruviQo'lda attach/detachAvtomatik (lifecycle-aware)
Ekran aylanishiRetain-fragmentViewModel omon qoladi
TestlashMock ViewContractBog'liqliklarsiz toza sinf
ReaktivlikPresenter-da callback-larLiveData/StateFlow/Combine

MVVM kamchiliklari — reaktiv zanjirlarni disk raskadrovka qilish murakkabligi va noto'g'ri obuna paytida xotira oqishi xavfi. LiveData hayot aylanishi xavfsizligi muammosini hal qiladi, StateFlow lifecycleScope talab qiladi, Combine — AnyCancellable bilan sink. MVP-da barcha chaqiruvlar ochiq (view.showUser), MVVM-da ma'lumotlar reaktiv oqim orqali keladi — kuzatish subscribe closure-ida debug breakpoint-larini talab qiladi. Ko'p StateFlow-li katta ViewModel-larda View ma'lum bir Flow-ga obuna bo'lmasa, UI yangilanishini o'tkazib yuborish mumkin.

MVP qachon yaxshiroq — minimal Android versiyasi API 21 dan (Android 5) past bo'lgan loyihalarda, Jetpack ViewModel AndroidX holda mavjud emas, va Combine holda toza UIKit-da (iOS 12 va past) loyihalarda. Hamma kod bazasi allaqachon MVP-da bo'lgan legacy loyihalar uchun MVVM-ga to'liq o'tish har doim ham oqlanmaydi — 3 oy ichida 100 ekranni qayta yozishdan ko'ra, bosqichma-bosqich mantiqni xizmatlarga chiqarib MVP-ni saqlash arzonroq.

Android va iOS-da ViewModel-ni testlash

ViewModel platforma bog'liqliklarisiz unit-testlar bilan tekshiriladi — bu MVVM foydasiga asosiy argumentdir. Android-da ViewModel Activity, Context yoki View-ni o'z ichiga olmaydi — barcha bog'liqliklar (Repository, UseCase) konstruktor orqali uzatiladi va mock obyektlari bilan almashtiriladi. iOS-da ObservableObject ilovani ishga tushirmasdan XCTest orqali tekshiriladi, bu testlarning barqarorligi va tezligini ta'minlaydi.

kotlin
// MockK bilan Android ViewModel unit-testi
class UserViewModelTest {

    private val repository = mockk<UserRepository>()
    private val viewModel = UserViewModel(repository)

    @Test
    fun loadUser_success_updatesState() = runTest {
        val user = User(1, "John", "john@test.com")
        coEvery { repository.getUser(1) } returns Result.success(user)

        viewModel.loadUser(1)

        assertEquals(UserState.Success(user), viewModel.state.value)
    }

    @Test
    fun loadUser_error_updatesErrorState() = runTest {
        val error = RuntimeException("Network error")
        coEvery { repository.getUser(1) } returns Result.failure(error)

        viewModel.loadUser(1)

        val state = viewModel.state.value
        assertTrue(state is UserState.Error)
        assertEquals("Network error", (state as UserState.Error).message)
    }
}

iOS ViewModel xuddi shunday tekshiriladi: mock UserService joylashtiramiz, loadUser chaqiramiz, holatni XCTestExpectation orqali tekshiramiz. Combine Publisher XCTestCase orqali wait(for: expectations, timeout: 1.0) bilan tekshiriladi. UserState tuzilmasi — associated values bilan enum — operatsiyadan keyin ekranning aniq holatini tekshirish imkonini beradi.

Kod qamrovi IT Sectr-ning MVVM-dagi loyihalarida ViewModel va Repository uchun 75-90% ni tashkil qiladi. ViewModel unit-testlar bilan, Repository test ma'lumotlar bazasi bilan integratsiya testlari bilan qoplanadi. SwiftUI va Jetpack Compose-da View kritik stsenariylar uchun UI testlari (XCUITest, Compose Test) bilan tekshiriladi. Qolgan UI skrinshot testlari (Snapshot Testing) bilan tekshiriladi — bu UI testlaridan tezroq va ko'rsatish to'g'riligiga 95% ishonch beradi.

Ko'p beriladigan savollar

MVVM va MVP o'rtasidagi asosiy farq nima?

MVVM-da ViewModel View-ga havolaga ega emas — ma'lumotlar reaktiv mexanizmlar (LiveData, StateFlow, @Published) orqali uzatiladi. MVP-da Presenter to'g'ridan-to'g'ri ViewContract interfeysi orqali View usullarini chaqiradi. MVVM ViewContract va qo'lda attach/detach-ni yo'q qiladi, ammo reaktiv oqimlarni tushunishni talab qiladi. ViewModel Android-da ekran aylanishidan omon qoladi, Presenter retain-fragment talab qiladi.

Android-da MVVM uchun qanday kutubxonalar kerak?

Minimal to'plam: lifecycle-viewmodel-ktx (ViewModel), lifecycle-livedata-ktx yoki kotlinx-coroutines-core (StateFlow). Inyeksiya uchun — Hilt yoki Koin. Asinxron operatsiyalar uchun — Kotlin Coroutines. Murakkab ma'lumot bog'lash uchun — DataBinding. Jetpack Compose-da (Google tomonidan 2022-yildan tavsiya etilgan) compose-runtime va lifecycle-viewmodel-compose yetarli.

Nega Apple iOS uchun MVVM-ni tavsiya qiladi?

SwiftUI (2019) reaktiv arxitektura uchun yaratilgan: @State va @Published ma'lumot o'zgarganda View-ni avtomatik qayta chizadi. MVVM SwiftUI-ga tabiiy moslikdir: View — @ViewBuilder, ViewModel — ObservableObject. Apple MVVM-ni yagona pattern sifatida majburlamaydi, ammo 2019-yildan boshlab barcha o'quv materiallari ViewModel + SwiftUI dan foydalanadi. UIKit uchun Apple MVC yoki Coordinator ni tavsiya qiladi.

ViewModel-da xotira oqishidan qanday qochish mumkin?

Android: viewModelScope ViewModel tozalanayotganda korutinlarni avtomatik bekor qiladi. iOS: Combine-dan AnyCancellable uni saqlaydigan obyekt bo'shatilganda avtomatik obunani bekor qiladi. SwiftUI @StateObject hayot aylanishini avtomatik boshqaradi. Asosiy qoidalar: ViewModel-da View/Context havolalarini saqlamaslik, tozalashda uzoq muddatli operatsiyalarni bekor qilish, closure-larda weak self ishlatish.

Android uchun LiveData yoki StateFlow tanlash?

StateFlow — zamonaviy tanlov. LiveData soddaroq va hayot aylanishi uchun xavfsiz, ammo StateFlow kuchliroq: korutinlar bilan ishlaydi, flatMap, combine, filter-ni qo'llab-quvvatlaydi, @Nullable annotatsiyasini talab qilmaydi. LiveData afzal bo'lgan yagona stsenariy — StateFlow (Kotlin Flow-API) mavjud bo'lmagan Java kodi bilan ishlash. Google Kotlin-dagi yangi loyihalar uchun StateFlow-ni tavsiya qiladi.

Xulosa

  • MVVM (Model-View-ViewModel) — ViewModel View-ga havolaga ega bo'lmagan reaktiv pattern
  • ViewModel — ekran aylanishidan omon qoladi, unit-testlar bilan tekshiriladi, UI-dan mustaqil
  • Android — ViewModel + StateFlow + Kotlin Coroutines — Google-dan zamonaviy stack
  • iOS — ObservableObject + @Published + SwiftUI — MVVM-ning mahalliy tatbiqi
  • MVVM vs MVP — MVVM ViewContract va qo'lda attach/detach-ni yo'q qiladi
  • Testlash — ViewModel platforma bog'liqliklarisiz unit-testlar bilan qoplanadi
  • Tavsiya — MVVM yangi loyihalar uchun; MVP legacy qo'llab-quvvatlash uchun

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