ViewModel एक Android Jetpack Architecture घटक है जो Activity और Fragment के जीवनचक्र को ध्यान में रखते हुए UI डेटा को संग्रहीत और प्रबंधित करने के लिए डिज़ाइन किया गया है। Google I/O 2025 के अनुसार, Jetpack पर बने 82% आधुनिक Android ऐप्स में ViewModel का उपयोग किया जाता है। सामान्य वर्गों के विपरीत, ViewModel स्वचालित रूप से स्क्रीन रोटेशन और अन्य कॉन्फ़िगरेशन परिवर्तनों से बच जाता है, बिना डेटा हानि के UI स्थिति बनाए रखता है। MVVM (Model-View-ViewModel) आर्किटेक्चर ViewModel पर एक केंद्रीय परत के रूप में निर्भर करता है जो व्यावसायिक तर्क को इंटरफ़ेस से जोड़ता है।
मुख्य बातें
ViewModel Android Jetpack लाइब्रेरी का एक वर्ग है जो उपयोगकर्ता इंटरफ़ेस से संबंधित डेटा को संग्रहीत और प्रबंधित करने के लिए डिज़ाइन किया गया है, जो Activity या Fragment के जीवनचक्र को ध्यान में रखता है। ViewModel का मुख्य कार्य डेटा तैयारी तर्क को UI परत से अलग करना और कॉन्फ़िगरेशन परिवर्तनों जैसे स्क्रीन रोटेशन, थीम परिवर्तन या लोकेल परिवर्तन के दौरान इस डेटा को संरक्षित करना है।
ViewModel के आगमन से पहले, डेवलपर्स UI स्थिति को सीधे Activity या Fragment में संग्रहीत करते थे। स्क्रीन घुमाने पर, Android Activity को नष्ट कर देता है और एक नया बनाता है — सभी असंग्रहीत डेटा खो जाता था। समाधान onSaveInstanceState() के माध्यम से स्थिति सहेजना या onRetainNonConfigurationInstance() का उपयोग करना था, लेकिन दोनों दृष्टिकोणों में मैन्युअल प्रबंधन और क्रमांकन की आवश्यकता थी और वे जटिल ऑब्जेक्ट के लिए उपयुक्त नहीं थे। ViewModel इस समस्या को फ्रेमवर्क स्तर पर हल करता है: डेटा UI से अलग मेमोरी में रहता है और Activity के पुनर्निर्माण पर स्वचालित रूप से वापस आ जाता है।
Android Developers दस्तावेज़ (2025) के अनुसार, ViewModel प्रक्रिया की RAM में डेटा संग्रहीत करता है — यह onSaveInstanceState() के माध्यम से Bundle से पुनर्स्थापित करने की तुलना में 10–50 गुना तेज़ है, जहाँ बाइट ऐरे में क्रमांकन की आवश्यकता होती है। ViewModel उन सभी स्क्रीन के लिए अनुशंसित है जहाँ डेटा साधारण प्रिमिटिव या स्ट्रिंग से अधिक जटिल है।
ViewModel जीवनचक्र मौलिक रूप से Activity जीवनचक्र से भिन्न है: ViewModel स्क्रीन रोटेशन पर नष्ट नहीं होता है और स्कोप के पूरी तरह समाप्त होने तक जीवित रहता है (Activity.finish() या Fragment हटा दिया गया)। इसका मतलब है कि ViewModel में लोड किया गया कोई भी डेटा नेटवर्क या डेटाबेस से पुनः लोड किए बिना कॉन्फ़िगरेशन परिवर्तनों के दौरान उपलब्ध रहता है।
Activity निर्माण के समय, सिस्टम ViewModelProvider के माध्यम से ViewModel आवंटित करता है। ViewModelProvider.get(ViewModel::class.java) की पहली कॉल पर एक नया ViewModel इंस्टेंस बनाया जाता है। बाद की कॉलों पर (रोटेशन के बाद भी) वही इंस्टेंस वापस आता है। ViewModel की सफाई स्वचालित रूप से onCleared() कॉल होने पर होती है — यह विधि तब लागू होती है जब Activity समाप्त (finish()) होती है या Fragment पूरी तरह हटा दिया जाता है। डेवलपर संसाधनों को मुक्त करने के लिए onCleared() को ओवरराइड कर सकता है: Flow से सदस्यता समाप्त करना, कोरूटीन रद्द करना, सॉकेट बंद करना।
Google Jetpack दस्तावेज़ में जोर देता है: ViewModel के अंदर कभी भी Activity या View का संदर्भ संग्रहीत न करें — इससे मेमोरी लीक होती है क्योंकि ViewModel अपने UI के साथ Activity से अधिक जीवित रहता है। इसके बजाय, ViewModel और UI के बीच डेटा स्थानांतरित करने के लिए LiveData, StateFlow या SavedStateHandle का उपयोग करें।
MVVM (Model-View-ViewModel) पैटर्न में, ViewModel View (Activity/Fragment) और Model (रिपॉजिटरी, DB, API) के बीच एक केंद्रीय स्थान रखता है। View ViewModel (LiveData, StateFlow) के रिएक्टिव डेटा की सदस्यता लेता है और उनके बदलने पर स्वचालित रूप से अपडेट होता है। ViewModel को View के अस्तित्व के बारे में पता नहीं है — यह केवल डेटा और कमांड प्रदान करता है, और View तय करता है कि उन्हें कैसे प्रदर्शित किया जाए।
MVP और MVVM की तुलना: MVP में, प्रेज़ेंटर सीधे View (इंटरफ़ेस) विधियों को कॉल करता है, जिससे कठोर युग्मन बनता है। MVVM में, ViewModel रिएक्टिव डेटा स्ट्रीम प्रकाशित करता है और View उनकी सदस्यता लेता है — कनेक्शन एकदिशीय और परीक्षण योग्य है। JetBrains Developer Survey (2024) के अनुसार, 68% Android डेवलपर MVVM को अपनी प्राथमिक आर्किटेक्चर के रूप में उपयोग करते हैं, और ViewModel इस पैटर्न का एक मुख्य घटक है।
IT Sectr में, हम 2018 से सभी व्यावसायिक Kotlin प्रोजेक्ट्स में MVVM का ViewModel के साथ उपयोग कर रहे हैं। अभ्यास से पता चलता है कि यह दृष्टिकोण जिम्मेदारियों के स्पष्ट पृथक्करण और एमुलेटर के बिना व्यावसायिक तर्क की परीक्षण क्षमता के कारण UI तर्क डीबगिंग समय को 30–40% तक कम करता है।
ViewModelProvider Fragment या Activity में ViewModel प्राप्त करने का मानक तरीका है। डिफ़ॉल्ट रूप से, ViewModelProvider बिना तर्क के खाली कंस्ट्रक्टर के माध्यम से ViewModel बनाता है। यदि ViewModel को पैरामीटर (जैसे रिपॉजिटरी या एप्लिकेशन कॉन्टेक्स्ट) की आवश्यकता है, तो ViewModelProvider.Factory को लागू करना आवश्यक है।
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
}
}
Fragment या Activity से ViewModel प्राप्त करते समय फ़ैक्टरी ViewModelProvider को दी जाती है। SavedStateHandle AndroidX 1.2.0 में शुरू किया गया एक वैकल्पिक पैरामीटर पासिंग तंत्र है: ViewModel स्वचालित रूप से कंस्ट्रक्टर के माध्यम से SavedStateHandle प्राप्त करता है, और तर्क कस्टम फ़ैक्टरी लिखे बिना Bundle के माध्यम से पास किए जाते हैं।
viewModelScope ViewModel में निर्मित और उसके जीवनचक्र से बंधा CoroutineScope है। viewModelScope में लॉन्च किए गए सभी कोरूटीन onCleared() कॉल होने पर स्वचालित रूप से रद्द हो जाते हैं, जो ViewModel नष्ट होने के बाद मेमोरी लीक और बैकग्राउंड ऑपरेशन को रोकता है।
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 कोरूटीन स्वचालित रूप से रद्द हो जाते हैं
}
}
viewModelScope में कोरूटीन डिफ़ॉल्ट रूप से Dispatchers.Main पर चलते हैं। नेटवर्क या डिस्क ऑपरेशन के लिए, withContext का उपयोग करके Dispatchers.IO पर स्विच करें या launch में डिस्पैचर निर्दिष्ट करें। Google (Android Dev Summit 2024) के अनुसार, मैन्युअल Job प्रबंधन की तुलना में viewModelScope का उपयोग कोरूटीन से संबंधित मेमोरी लीक को 95% तक कम करता है।
Hilt Dagger पर निर्मित Android के लिए Google की आधिकारिक डिपेंडेंसी इंजेक्शन लाइब्रेरी है। Hilt के साथ, ViewModelProvider.Factory को मैन्युअल रूप से लिखने की आवश्यकता नहीं है — बस ViewModel कंस्ट्रक्टर को @HiltViewModel एनोटेशन से एनोटेट करें। Hilt स्वचालित रूप से फ़ैक्टरी बनाता है और कंस्ट्रक्टर में घोषित डिपेंडेंसी को इंजेक्ट करता है।
@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 में — बिना फ़ैक्टरी के:
val viewModel: ProfileViewModel = by viewModels()
Koin कोड जनरेशन के बिना एक वैकल्पिक DI लाइब्रेरी है। Koin में, ViewModel को viewModel { } के माध्यम से मॉड्यूल में घोषित किया जाता है, और Fragment में by viewModel() के माध्यम से प्राप्त किया जाता है। Hilt और Koin के बीच चुनाव प्रोजेक्ट पर निर्भर करता है: Hilt कंपाइल समय पर डिपेंडेंसी ग्राफ सत्यापन प्रदान करता है, Koin हल्का है और kapt/ksp की आवश्यकता नहीं है। IT Sectr में, हम बड़े प्रोजेक्ट्स (50 से अधिक स्क्रीन) में Hilt और मध्यम प्रोजेक्ट्स में Koin का उपयोग करते हैं।
एक सरल ViewModel जो एक पूर्णांक काउंटर संग्रहीत करता है जो स्क्रीन रोटेशन पर रीसेट नहीं होता है। MutableLiveData और LiveData के उपयोग के बुनियादी पैटर्न को प्रदर्शित करता है।
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
}
}
ViewModel जो सिस्टम द्वारा प्रक्रिया समाप्त होने पर भी स्वचालित रूप से स्थिति संरक्षित करने के लिए SavedStateHandle का उपयोग करता है। SavedStateHandle एकमात्र तंत्र है जो ऐप को बैकग्राउंड में छोटा करने और समाप्त करने पर डेटा सहेजता है।
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
}
}
SavedStateHandle से LiveData स्वचालित रूप से अंतिम मान Bundle में सहेजता है। प्रक्रिया के पुनर्निर्माण पर (उदाहरण के लिए, ऐप को छोटा करने और बंद करने के बाद), Bundle पुनर्स्थापित हो जाता है और LiveData पिछला मान प्राप्त करता है। Google परीक्षणों के अनुसार, SavedStateHandle Bundle में 5 KB तक डेटा सहेजने की गारंटी देता है — टेक्स्ट फ़ील्ड, ID और क्रमांकित JSON ऑब्जेक्ट के लिए पर्याप्त।
अक्सर पूछे जाने वाले प्रश्न
ViewModel प्रक्रिया की RAM में डेटा संग्रहीत करता है — यह बिना क्रमांकन के तुरंत उपलब्ध होता है, जटिल ऑब्जेक्ट (सूचियाँ, Bitmap, नेटवर्क प्रतिक्रियाएँ) के लिए उपयुक्त है। onSaveInstanceState() डेटा को Bundle में क्रमांकित करता है (Android 12 से शुरू प्रति लेनदेन अधिकतम 1 MB) और केवल सरल प्रिमिटिव, String और Serializable/Parcelable के लिए उपयुक्त है। ViewModel + SavedStateHandle Google द्वारा अनुशंसित संयोजन है: रनटाइम डेटा के लिए ViewModel, प्रक्रिया समाप्त होने पर पुनर्स्थापना के लिए SavedStateHandle।
नहीं, सिस्टम स्वचालित रूप से स्कोप समाप्त होने पर onCleared() को कॉल करता है। viewModelStore.clear() के माध्यम से मैन्युअल सफाई केवल परीक्षण मामलों के बीच लीक को रोकने के लिए आवश्यक है। प्रोडक्शन कोड में, कभी भी मैन्युअल रूप से clear() को कॉल न करें — यह ViewModel जीवनचक्र को तोड़ता है और अप्रत्याशित UI व्यवहार का कारण बन सकता है।
हाँ, ViewModel Jetpack Compose में viewModel() फ़ंक्शन के माध्यम से पूरी तरह से समर्थित है। Compose में, ViewModel Composable स्कोप स्तर पर प्राप्त होता है और स्कोप से बाहर निकलने पर स्वचालित रूप से साफ़ हो जाता है। MVVM का Compose संस्करण Unidirectional Data Flow (UDF) कहलाता है: ViewModel StateFlow प्रकाशित करता है, और Composable फ़ंक्शन collectAsState() के माध्यम से सदस्यता लेते हैं। reducer दृष्टिकोण का Compose संस्करण ViewModel के साथ MVI है।
Activity, Fragment, View, Context (Application को छोड़कर) के संदर्भ संग्रहीत करना निषिद्ध है। यह मेमोरी लीक का कारण बनता है क्योंकि ViewModel UI कॉन्टेक्स्ट से अधिक जीवित रहता है। क्रमांकित View स्थितियाँ (जैसे RecyclerView स्थिति) संग्रहीत न करें — LayoutManager.onSaveInstanceState() का उपयोग करें। बड़ी मात्रा में डेटा (10 MB से अधिक) संग्रहीत करने से बचें — प्रक्रिया को छोटा करने पर, SavedStateHandle के बिना डेटा खो जाएगा।
ViewModel का परीक्षण बिना एमुलेटर के सामान्य Kotlin वर्ग की तरह किया जाता है: इंस्टेंस बनाएँ, विधियाँ कॉल करें, LiveData या StateFlow की स्थिति जाँचें। कोरूटीन के परीक्षण के लिए, TestDispatcher के साथ kotlinx-coroutines-test से runTest का उपयोग करें। Hilt के साथ ViewModel के लिए, परीक्षण Fragment में @HiltViewModelTest और hiltViewModel() का उपयोग करें। Google के अनुसार, यूनिट परीक्षण इंस्ट्रुमेंटेड परीक्षणों के बिना ViewModel तर्क का 80–90% कवर करते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें