ViewModel की खास जानकारी Android Jetpack का हिस्सा है.

ViewModel क्लास, बिज़नेस लॉजिक या स्क्रीन लेवल की स्थिति है होल्डर चुनें. यह यूज़र इंटरफ़ेस (यूआई) को स्थिति की जानकारी देता है और उससे जुड़े बिज़नेस लॉजिक को शामिल करता है. इसका मुख्य लाभ यह है कि यह स्थिति को कैश मेमोरी में सेव करता है और उसे लगातार बनाए रखता है कॉन्फ़िगरेशन में बदलाव किए गए हैं. इसका मतलब है कि आपके यूज़र इंटरफ़ेस (यूआई) को फिर से डेटा फ़ेच करने की ज़रूरत नहीं है गतिविधियों के बीच नेविगेट करते समय या कॉन्फ़िगरेशन में किए गए बदलावों जैसे, घुमाते समय इसका ध्यान रखें.

राज्य का मालिकाना हक रखने वाले लोगों के बारे में ज़्यादा जानने के लिए, राज्य के मालिकों से जुड़े दिशा-निर्देश देखें. इसी तरह, यूज़र इंटरफ़ेस (यूआई) लेयर के बारे में ज़्यादा जानकारी के लिए, यूज़र इंटरफ़ेस (यूआई) लेयर देखें दिशा-निर्देश.

ViewModel के फ़ायदे

ViewModel का विकल्प एक सादा क्लास है, जिसमें आपका दिखाया जाने वाला डेटा होता है आपके यूज़र इंटरफ़ेस (यूआई) में. इससे गतिविधियों या नेविगेशन डेस्टिनेशन. ऐसा करने से, सेव न किए जाने पर डेटा मिट जाता है सेव करने के इंस्टेंस की स्थिति दिखाने के तरीके का इस्तेमाल करके. ViewModel आसानी से डेटा परसिस्टेंस के लिए एपीआई, जो इस समस्या को हल करता है.

ViewModel क्लास के मुख्य फ़ायदे दो हैं:

  • इसकी मदद से, यूज़र इंटरफ़ेस (यूआई) की स्थिति को बनाए रखा जा सकता है.
  • इससे आपको कारोबारी लॉजिक का ऐक्सेस मिलता है.

निरंतरता

ViewModel, ViewModel की ओर से धारण की जाने वाली स्थिति में, और कार्रवाइयां जिन्हें ViewModel ट्रिगर करता है. कैश मेमोरी में सेव होने का मतलब है कि कॉन्फ़िगरेशन में किए गए सामान्य बदलावों, जैसे कि स्क्रीन के ज़रिए डेटा को फिर से फ़ेच करने के लिए घुमाव.

दायरा

जब ViewModel इंस्टैंशिएट किया जाता है, तो कोई ऐसा ऑब्जेक्ट पास किया जाता है जो ViewModelStoreOwner इंटरफ़ेस. यह नेविगेशन डेस्टिनेशन हो सकता है, नेविगेशन ग्राफ़, गतिविधि, फ़्रैगमेंट या कोई भी दूसरा टाइप, जो इंटरफ़ेस पर कॉपी करने की सुविधा मिलती है. इसके बाद, आपका Viewmodel लाइफ़साइकल ViewModelStoreOwner. यह ViewModelStoreOwner तक मेमोरी में सेव रहता है हमेशा के लिए हट जाता है.

क्लास की रेंज, डायरेक्ट या इनडायरेक्ट या इनडायरेक्ट सब-क्लास होती है: ViewModelStoreOwner इंटरफ़ेस. डायरेक्ट सब-क्लास ComponentActivity, Fragment, और NavBackStackEntry. इनडायरेक्ट सब-क्लास की पूरी सूची देखने के लिए, ViewModelStoreOwner रेफ़रंस.

जब ViewModel के स्कोप वाला फ़्रैगमेंट या गतिविधि खत्म हो जाती है, इसके दायरे में आने वाले ViewModel में एसिंक्रोनस काम जारी रहता है. यह है लंबे समय तक टिके रहने के लिए ज़रूरी है.

ज़्यादा जानकारी के लिए, नीचे ViewModel लाइफ़साइकल सेक्शन देखें.

सेव किया गया स्टेटहैंडल

SaveStateHandle की मदद से सिर्फ़ कॉन्फ़िगरेशन के ज़रिए ही डेटा सेव करके रखा जा सकता है बदलाव, लेकिन पूरी प्रोसेस के दौरान होते हैं. इसका मतलब है कि इसकी मदद से, यूज़र इंटरफ़ेस (यूआई) को उपयोगकर्ता के ऐप्लिकेशन बंद करने और उसे बाद में खोलने पर भी उस स्थिति में कोई बदलाव नहीं होता.

कारोबारी लॉजिक का ऐक्सेस

भले ही डेटा में ज़्यादातर कारोबारी लॉजिक मौजूद हों लेयर है, तो यूज़र इंटरफ़ेस (यूआई) लेयर में बिज़नेस लॉजिक भी शामिल हो सकता है. ऐसा तब हो सकता है जब कई डेटा स्टोर करने की जगहों से डेटा को आपस में जोड़कर, स्क्रीन के यूज़र इंटरफ़ेस (यूआई) की स्थिति बनाना या किसी खास तरह के डेटा के लिए डेटा लेयर की ज़रूरत नहीं होती.

यूज़र इंटरफ़ेस (यूआई) लेयर में बिज़नेस लॉजिक को मैनेज करने के लिए, ViewModel सही जगह है. कॉन्टेंट बनाने ViewModel, इवेंट को मैनेज करने और उन्हें दूसरे संगठनों को सौंपने का काम भी मैनेज करता है ये लेयर और कैटगरी, जब बदलाव करने के लिए कारोबारी नियम को लागू करने की ज़रूरत होती है का इस्तेमाल किया जा सकता है.

Jetpack Compose

Jetpack Compose का इस्तेमाल करते समय, ViewModel स्क्रीन यूज़र इंटरफ़ेस (यूआई) को दिखाने का मुख्य तरीका है आपके कंपोज़ेबल में जोड़ी जा सकती हैं. हाइब्रिड ऐप्लिकेशन में, अलग-अलग ऐक्टिविटी और फ़्रैगमेंट आसानी से होस्ट होते हैं आपके कंपोज़ेबल फ़ंक्शन को एक्ज़ीक्यूट करने की ज़रूरत नहीं पड़ेगी. यह तरीका पिछले तरीकों से शिफ़्ट हो रहा है, जहां ऐसा नहीं था इसे इस्तेमाल करना, यूज़र इंटरफ़ेस (यूआई) के अलग-अलग तरह के हिस्सों को बनाने में आसान और फ़्रैगमेंट की वजह से, वे यूज़र इंटरफ़ेस (यूआई) कंट्रोलर के तौर पर ज़्यादा ऐक्टिव हो गए.

कंपोज़ के साथ ViewModel का इस्तेमाल करते समय, सबसे ज़रूरी बात यह है कि ऐसा हो सकता है कि किसी ViewModel को कंपोज़ेबल में शामिल न किया जा सके. ऐसा इसलिए है, क्योंकि कंपोज़ेबल एक ViewModelStoreOwner नहीं है. इसमें एक ही कंपोज़ेबल के दो इंस्टेंस कंपोज़िशन या दो अलग-अलग कंपोज़ेबल जो एक ही ViewModel टाइप का इस्तेमाल करते हों उसी ViewModelStoreOwner के तहत एक ही इंस्टेंस मिलेगा ViewModel, जो अक्सर उम्मीद के मुताबिक नहीं होता.

कंपोज़ में ViewModel के फ़ायदे पाने के लिए, हर स्क्रीन को फ़्रैगमेंट में होस्ट करें या ऐक्टिविटी या कंपोज़ेबल में नेविगेशन का इस्तेमाल करें और कंपोज़ेबल में ViewModels का इस्तेमाल करें नेविगेशन डेस्टिनेशन के जितना हो सके उतना करीब से फ़ंक्शन करता है. ऐसा इसलिए, क्योंकि ViewModel को नेविगेशन डेस्टिनेशन, नेविगेशन ग्राफ़, और गतिविधियां और फ़्रैगमेंट.

ज़्यादा जानकारी के लिए, Jetpack Compose के लिए स्टेट लिफ़्ट से जुड़ी गाइड देखें.

ViewModel लागू करना

नीचे दी गई स्क्रीन के लिए ViewModel को लागू करने का एक उदाहरण दिया गया है, जिससे उपयोगकर्ता पासा फेंक सकता है.

Kotlin

data class DiceUiState(
    val firstDieValue: Int? = null,
    val secondDieValue: Int? = null,
    val numberOfRolls: Int = 0,
)

class DiceRollViewModel : ViewModel() {

    // Expose screen UI state
    private val _uiState = MutableStateFlow(DiceUiState())
    val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()

    // Handle business logic
    fun rollDice() {
        _uiState.update { currentState ->
            currentState.copy(
                firstDieValue = Random.nextInt(from = 1, until = 7),
                secondDieValue = Random.nextInt(from = 1, until = 7),
                numberOfRolls = currentState.numberOfRolls + 1,
            )
        }
    }
}

Java

public class DiceUiState {
    private final Integer firstDieValue;
    private final Integer secondDieValue;
    private final int numberOfRolls;

    // ...
}

public class DiceRollViewModel extends ViewModel {

    private final MutableLiveData<DiceUiState> uiState =
        new MutableLiveData(new DiceUiState(null, null, 0));
    public LiveData<DiceUiState> getUiState() {
        return uiState;
    }

    public void rollDice() {
        Random random = new Random();
        uiState.setValue(
            new DiceUiState(
                random.nextInt(7) + 1,
                random.nextInt(7) + 1,
                uiState.getValue().getNumberOfRolls() + 1
            )
        );
    }
}

इसके बाद, ऐक्टिविटी से ViewModel को ऐक्सेस किया जा सकता है. इसके लिए, यह तरीका अपनाएं:

Kotlin

import androidx.activity.viewModels

class DiceRollActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same DiceRollViewModel instance created by the first activity.

        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        val viewModel: DiceRollViewModel by viewModels()
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect {
                    // Update UI elements
                }
            }
        }
    }
}

Java

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.
        DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
        model.getUiState().observe(this, uiState -> {
            // update UI
        });
    }
}

Jetpack Compose

import androidx.lifecycle.viewmodel.compose.viewModel

// Use the 'viewModel()' function from the lifecycle-viewmodel-compose artifact
@Composable
fun DiceRollScreen(
    viewModel: DiceRollViewModel = viewModel()
) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    // Update UI elements
}

ViewModel के साथ कोरूटीन इस्तेमाल करना

ViewModel में Kotlin कोरूटीन के साथ काम किया जा सकता है. यह लंबे समय तक टिके रहने में के साथ उसी तरह काम करता रहेगा जैसे यह यूज़र इंटरफ़ेस (यूआई) स्थिति में होता है.

ज़्यादा जानकारी के लिए, Android आर्किटेक्चर के साथ Kotlin कोरूटीन इस्तेमाल करना कॉम्पोनेंट.

ViewModel की लाइफ़साइकल

ViewModel का लाइफ़साइकल सीधे इसके स्कोप से जुड़ा होता है. ViewModel ViewModelStoreOwner के दायरे में आने तक, मेमोरी में सेव रहता है गायब हो जाता है. ऐसा इन स्थितियों में हो सकता है:

  • गतिविधि के मामले में, जब वह पूरी होती है.
  • फ़्रैगमेंट के मामले में, जब यह अलग हो जाता है.
  • नेविगेशन एंट्री के मामले में, जब उसे पिछली गतिविधियों से हटाया जाता है.

इसकी वजह से ViewModels, बचे रहने वाले डेटा को स्टोर करने का बेहतरीन तरीका बन जाता है कॉन्फ़िगरेशन में बदलाव किए गए हैं.

पहली इमेज में, किसी गतिविधि के लाइफ़साइकल की अलग-अलग स्थितियां दिखाई गई हैं घुमाएँ और फिर समाप्त हो जाता है. इस इलस्ट्रेशन में, ViewModel, इससे जुड़ी गतिविधि की लाइफ़साइकल के बगल में मौजूद है. यह खास डायग्राम में किसी गतिविधि की स्थिति को दिखाया गया है. समान मूल स्थितियां इन पर लागू होती हैं फ़्रैगमेंट का लाइफ़साइकल.

गतिविधि के बदलाव की स्थिति के तौर पर ViewModel की लाइफ़साइकल दिखाता है.

आम तौर पर, सिस्टम जब पहली बार किसीViewModel ऐक्टिविटी ऑब्जेक्ट का onCreate() तरीका. सिस्टम कॉल कर सकता है onCreate() किसी गतिविधि की मौजूदगी के दौरान कई बार, जैसे जैसे कि डिवाइस की स्क्रीन घुमाई जाती है. ViewModel तब से मौजूद होता है, जब से गतिविधि खत्म होने और खत्म होने तक, पहले ViewModel का अनुरोध करें.

ViewModel डिपेंडेंसी मिटाना

ViewModel, onCleared तरीके को तब कॉल करता है, जब ViewModelStoreOwner लाइफ़साइकल के दौरान उसे तबाह कर देता है. इससे आपको स्टोरेज खाली करने में मदद मिलती है या डिपेंडेंसी जो ViewModel के लाइफ़साइकल को फ़ॉलो करती है.

नीचे दिए गए उदाहरण में, viewModelScope का विकल्प दिखाया गया है. viewModelScope पहले से मौजूद CoroutineScope है, जो अपने-आप ViewModel के लाइफ़साइकल को फ़ॉलो करता है. ViewModel इसका इस्तेमाल इन कामों के लिए करता है कारोबार से जुड़ी कार्रवाइयों को ट्रिगर करने में मदद करे. अगर आपको इसके बजाय कस्टम स्कोप का इस्तेमाल करना है, तो आसान टेस्टिंग के लिए viewModelScope का इस्तेमाल करने पर, ViewModel CoroutineScope को इसके कंस्ट्रक्टर में डिपेंडेंसी के तौर पर इस्तेमाल करता है. जब ViewModelStoreOwner अपनी लाइफ़साइकल खत्म होने पर ViewModel को साफ़ करता है, ViewModel CoroutineScope को भी रद्द कर देता है.

class MyViewModel(
    private val coroutineScope: CoroutineScope =
        CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
) : ViewModel() {

    // Other ViewModel logic ...

    override fun onCleared() {
        coroutineScope.cancel()
    }
}

लाइफ़साइकल 2.5 और इसके बाद के वर्शन से, एक या उससे ज़्यादा Closeable पास किए जा सकते हैं ऑब्जेक्ट को ViewModel के कंस्ट्रक्टर पर अपलोड करता है, जो ViewModel इंस्टेंस मिटा दिया गया है.

class CloseableCoroutineScope(
    context: CoroutineContext = SupervisorJob() + Dispatchers.Main.immediate
) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context
    override fun close() {
        coroutineContext.cancel()
   }
}

class MyViewModel(
    private val coroutineScope: CoroutineScope = CloseableCoroutineScope()
) : ViewModel(coroutineScope) {
    // Other ViewModel logic ...
}

सबसे सही तरीके

इन सबसे सही तरीकों को अपनाना चाहिए ViewModel:

  • इनकी स्कोपिंग की वजह से, ViewModels का इस्तेमाल स्क्रीन लेवल स्टेट होल्डर. उनका इस्तेमाल फिर से इस्तेमाल किए जा सकने वाले यूज़र इंटरफ़ेस (यूआई) के स्टेट होल्डर के तौर पर न करें कॉम्पोनेंट, जैसे कि चिप ग्रुप या फ़ॉर्म. ऐसा न करने पर, आपको पहले जैसा ही एक ही फ़ॉर्मैट में, एक ही यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट के अलग-अलग इस्तेमाल में ViewModel इंस्टेंस जब तक आप हर चिप के लिए, व्यू मॉडल कुंजी साफ़ तौर पर इस्तेमाल न करें, तब तक ViewModelStoreOwner ऐसा करता है.
  • ViewModels को यूज़र इंटरफ़ेस (यूआई) लागू करने की जानकारी के बारे में पता नहीं होना चाहिए. नामों को रखें ViewModel API जिन तरीकों को दिखाता है और यूज़र इंटरफ़ेस (यूआई) की स्थिति वाले फ़ील्ड सामान्य रखना चाहिए. इस तरह से, आपका ViewModel हर तरह के यूज़र इंटरफ़ेस (यूआई): मोबाइल फ़ोन, फ़ोल्ड किया जा सकने वाला डिवाइस, टैबलेट या Chromebook!
  • ये ViewModelStoreOwner के मुकाबले ज़्यादा समय तक चलते हैं, इसलिए ViewModels उसमें लाइफ़साइकल से जुड़े एपीआई का कोई रेफ़रंस नहीं होना चाहिए, जैसे कि Context या मेमोरी लीक होने से रोकने के लिए Resources.
  • ViewModels को अन्य क्लास, फ़ंक्शन या अन्य यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट में पास न करें. यह प्लैटफ़ॉर्म इन्हें मैनेज करता है. इसलिए, आपको इन्हें अपने जितना ही करीब रखना चाहिए कर सकते हैं. आपकी ऐक्टिविटी, फ़्रैगमेंट या स्क्रीन लेवल पर कंपोज़ेबल फ़ंक्शन के पास की जानकारी. यह निचले लेवल के कॉम्पोनेंट को, इससे ज़्यादा डेटा और लॉजिक ऐक्सेस करने से रोकता है उनकी ज़रूरत को पूरा किया जा सकता है.

ज़्यादा जानकारी

जैसे-जैसे आपका डेटा ज़्यादा जटिल होता जाएगा, हो सकता है कि आप एक अलग क्लास का इस्तेमाल करें. ViewModel का मकसद, डेटा को इनकैप्सुलेट करना है यूज़र इंटरफ़ेस (यूआई) कंट्रोलर, जो डेटा को कॉन्फ़िगरेशन में होने वाले बदलावों के बाद भी सुरक्षित रखता है. जानकारी के लिए कॉन्फ़िगरेशन बदलावों में डेटा को लोड करने, बनाए रखने, और मैनेज करने के तरीके के बारे में जानने के लिए, सेव किए गए यूज़र इंटरफ़ेस (यूआई) की स्थितियां.

Android ऐप्लिकेशन आर्किटेक्चर की गाइड, रिपॉज़िटरी क्लास बनाने का सुझाव देती है का इस्तेमाल करें.

अन्य संसाधन

ViewModel क्लास के बारे में ज़्यादा जानकारी के लिए, इन्हें देखें संसाधन.

दस्तावेज़

सैंपल