सिद्धांत और Jetpack Compose को लागू करना
इस गाइड में, यूज़र इंटरफ़ेस (यूआई) की स्थिति के बारे में उपयोगकर्ता की उम्मीदों के बारे में बताया गया है. साथ ही, स्थिति को बनाए रखने के लिए उपलब्ध विकल्पों के बारे में बताया गया है.
सिस्टम के ऐप्लिकेशन या ऐक्टिविटी बंद करने के बाद, ऐक्टिविटी के यूज़र इंटरफ़ेस (यूआई) की स्थिति को तुरंत सेव और वापस लाना ज़रूरी है. इससे उपयोगकर्ता को बेहतर अनुभव मिलता है. उपयोगकर्ता यह उम्मीद करते हैं कि यूज़र इंटरफ़ेस (यूआई) की स्थिति में कोई बदलाव नहीं होगा. हालांकि, सिस्टम गतिविधि और उसकी सेव की गई स्थिति को मिटा सकता है.
उपयोगकर्ता की उम्मीदों और सिस्टम के व्यवहार के बीच के अंतर को कम करने के लिए, इन तरीकों का इस्तेमाल करें:
ViewModelऑब्जेक्ट.- इन कॉन्टेक्स्ट में सेव की गई इंस्टेंस की स्थितियां:
- व्यू:
onSaveInstanceState()एपीआई. - ViewModels:
SavedStateHandle.
- व्यू:
- यह कुकी, ऐप्लिकेशन और गतिविधि के ट्रांज़िशन के दौरान यूज़र इंटरफ़ेस (यूआई) की स्थिति को बनाए रखने के लिए लोकल स्टोरेज का इस्तेमाल करती है.
सबसे सही समाधान, आपके यूज़र इंटरफ़ेस (यूआई) डेटा की जटिलता, आपके ऐप्लिकेशन के इस्तेमाल के उदाहरणों, और डेटा ऐक्सेस करने की स्पीड और मेमोरी के इस्तेमाल के बीच संतुलन बनाने पर निर्भर करता है.
पक्का करें कि आपका ऐप्लिकेशन, उपयोगकर्ताओं की उम्मीदों के मुताबिक हो. साथ ही, यह तेज़ और रिस्पॉन्सिव इंटरफ़ेस उपलब्ध कराता हो. यूज़र इंटरफ़ेस (यूआई) में डेटा लोड करने में देरी न हो. खास तौर पर, रोटेशन जैसे सामान्य कॉन्फ़िगरेशन में बदलाव के बाद.
उपयोगकर्ता की उम्मीदें और सिस्टम का व्यवहार
उपयोगकर्ता की कार्रवाई के आधार पर, उन्हें उम्मीद होती है कि गतिविधि की स्थिति या तो मिटा दी जाएगी या सेव रखी जाएगी. कुछ मामलों में, सिस्टम अपने-आप वह काम करता है जो उपयोगकर्ता चाहता है. अन्य मामलों में, सिस्टम इसके उलट काम करता है.
उपयोगकर्ता के अनुरोध पर यूज़र इंटरफ़ेस (यूआई) की स्थिति को खारिज करना
उपयोगकर्ता यह उम्मीद करता है कि जब वह कोई गतिविधि शुरू करता है, तो उस गतिविधि की ट्रांज़िएंट यूज़र इंटरफ़ेस (यूआई) स्थिति तब तक एक जैसी बनी रहे, जब तक वह गतिविधि को पूरी तरह से खारिज नहीं कर देता. उपयोगकर्ता, यहां दिया गया तरीका अपनाकर किसी गतिविधि को पूरी तरह से खारिज कर सकता है:
- गतिविधि को खास जानकारी (हाल ही के ऐप्लिकेशन) वाली स्क्रीन से हटाना.
- सेटिंग स्क्रीन से ऐप्लिकेशन को बंद करना या उसे ज़बरदस्ती बंद करना.
- डिवाइस को रीबूट किया जा रहा है.
- "फ़िनिशिंग" से जुड़ी कोई कार्रवाई पूरी करना. यह कार्रवाई
Activity.finish()की मदद से की जाती है.
इन मामलों में, उपयोगकर्ता यह मान लेता है कि वह गतिविधि से हमेशा के लिए हट गया है. अगर वह गतिविधि को फिर से खोलता है, तो उसे उम्मीद होती है कि गतिविधि बिलकुल शुरू से शुरू होगी. इन खारिज करने के उदाहरणों के लिए, सिस्टम का बुनियादी व्यवहार उपयोगकर्ता की उम्मीदों से मेल खाता है. गतिविधि का इंस्टेंस डिस्ट्रॉय हो जाएगा और मेमोरी से हटा दिया जाएगा. साथ ही, इसमें सेव किया गया कोई भी स्टेट और गतिविधि से जुड़ा कोई भी सेव किया गया इंस्टेंस स्टेट रिकॉर्ड भी हटा दिया जाएगा.
पूरी तरह से खारिज करने के इस नियम के कुछ अपवाद हैं. उदाहरण के लिए, कोई उपयोगकर्ता ब्राउज़र से बाहर निकलने के लिए 'वापस जाएं' बटन का इस्तेमाल करता है. ऐसे में, वह उम्मीद कर सकता है कि ब्राउज़र उसे उसी वेबपेज पर ले जाए जिसे वह पहले देख रहा था.
सिस्टम की ओर से यूज़र इंटरफ़ेस (यूआई) की स्थिति को खारिज करना
कोई उपयोगकर्ता यह उम्मीद करता है कि कॉन्फ़िगरेशन में होने वाले बदलाव के दौरान, किसी गतिविधि के यूज़र इंटरफ़ेस (यूआई) की स्थिति में कोई बदलाव न हो. जैसे, डिवाइस को घुमाने या मल्टी-विंडो मोड में स्विच करने के दौरान. हालांकि, डिफ़ॉल्ट रूप से सिस्टम, कॉन्फ़िगरेशन में इस तरह का बदलाव होने पर ऐक्टिविटी को बंद कर देता है. इससे ऐक्टिविटी इंस्टेंस में सेव किया गया यूज़र इंटरफ़ेस (यूआई) स्टेट मिट जाता है. डिवाइस कॉन्फ़िगरेशन के बारे में ज़्यादा जानने के लिए, कॉन्फ़िगरेशन रेफ़रंस पेज देखें.
ध्यान दें कि कॉन्फ़िगरेशन में बदलाव करने के लिए, डिफ़ॉल्ट व्यवहार को बदला जा सकता है. हालांकि, ऐसा करने का सुझाव नहीं दिया जाता. ज़्यादा जानकारी के लिए, कॉन्फ़िगरेशन में हुए बदलाव को मैनेज करना लेख पढ़ें.
उपयोगकर्ता यह भी उम्मीद करता है कि अगर वह कुछ समय के लिए किसी दूसरे ऐप्लिकेशन पर स्विच करता है और फिर बाद में आपके ऐप्लिकेशन पर वापस आता है, तो आपकी गतिविधि के यूज़र इंटरफ़ेस (यूआई) की स्थिति पहले जैसी ही बनी रहेगी. उदाहरण के लिए, उपयोगकर्ता आपकी खोज गतिविधि में कोई खोज करता है. इसके बाद, वह होम बटन दबाता है या किसी फ़ोन कॉल का जवाब देता है. जब वह खोज गतिविधि पर वापस आता है, तो उसे खोज के लिए इस्तेमाल किया गया कीवर्ड और नतीजे पहले की तरह ही दिखने चाहिए.
इस स्थिति में, आपका ऐप्लिकेशन बैकग्राउंड में रखा जाता है. साथ ही, सिस्टम आपके ऐप्लिकेशन की प्रोसेस को मेमोरी में बनाए रखने की पूरी कोशिश करता है. हालांकि, जब उपयोगकर्ता किसी दूसरे ऐप्लिकेशन का इस्तेमाल कर रहा होता है, तब सिस्टम ऐप्लिकेशन की प्रोसेस को बंद कर सकता है. ऐसे में, गतिविधि का इंस्टेंस और उसमें सेव किया गया कोई भी डेटा मिट जाता है. जब उपयोगकर्ता ऐप्लिकेशन को फिर से लॉन्च करता है, तो गतिविधि का डेटा सेव नहीं होता. प्रोसेस बंद होने के बारे में ज़्यादा जानने के लिए, प्रोसेस और ऐप्लिकेशन का लाइफ़साइकल देखें.
यूज़र इंटरफ़ेस (यूआई) की स्थिति को बनाए रखने के विकल्प
जब यूज़र इंटरफ़ेस (यूआई) की स्थिति के बारे में उपयोगकर्ता की उम्मीदें, सिस्टम के डिफ़ॉल्ट व्यवहार से मेल नहीं खाती हैं, तो आपको उपयोगकर्ता के यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव और रीस्टोर करना होगा. इससे यह पक्का किया जा सकेगा कि सिस्टम की ओर से शुरू की गई प्रोसेस के बारे में उपयोगकर्ता को पता हो.
यूज़र इंटरफ़ेस (यूआई) की स्थिति को बनाए रखने के हर विकल्प में, यहां दिए गए डाइमेंशन के हिसाब से अंतर होता है. इनसे उपयोगकर्ता अनुभव पर असर पड़ता है:
ViewModel |
सेव किए गए इंस्टेंस की स्थिति |
स्थायी जगह |
|
सेव करने की जगह |
मेमोरी में |
मेमोरी में |
डिस्क या नेटवर्क पर |
कॉन्फ़िगरेशन में बदलाव होने पर भी बना रहता है |
हां |
हां |
हां |
सिस्टम की वजह से प्रोसेस बंद होने पर भी बना रहता है |
नहीं |
हां |
हां |
उपयोगकर्ता के गतिविधि को खारिज करने या finish() फ़ंक्शन का इस्तेमाल करने के बाद भी मौजूद रहता है |
नहीं |
नहीं |
हां |
डेटा से जुड़ी सीमाएं |
जटिल ऑब्जेक्ट ठीक हैं, लेकिन उपलब्ध मेमोरी के हिसाब से स्पेस सीमित है |
सिर्फ़ प्रिमिटिव टाइप और आसान, छोटे ऑब्जेक्ट के लिए, जैसे कि |
यह सिर्फ़ डिस्क स्पेस या नेटवर्क संसाधन से डेटा वापस पाने की लागत / समय के हिसाब से सीमित होता है |
पढ़ने/लिखने का समय |
क्विक (सिर्फ़ मेमोरी ऐक्सेस करने के लिए) |
धीमा (सीरियलाइज़ेशन/डीसीरियलाइज़ेशन की ज़रूरत होती है) |
धीमा (इसके लिए डिस्क ऐक्सेस या नेटवर्क लेन-देन की ज़रूरत होती है) |
कॉन्फ़िगरेशन में होने वाले बदलावों को हैंडल करने के लिए ViewModel का इस्तेमाल करना
ViewModel, यूज़र इंटरफ़ेस (यूआई) से जुड़े डेटा को सेव करने और मैनेज करने के लिए सबसे सही है. ऐसा तब होता है, जब उपयोगकर्ता ऐप्लिकेशन का इस्तेमाल कर रहा हो. इससे यूज़र इंटरफ़ेस (यूआई) के डेटा को तुरंत ऐक्सेस किया जा सकता है. साथ ही, यह रोटेशन, विंडो का साइज़ बदलने, और कॉन्फ़िगरेशन में होने वाले अन्य सामान्य बदलावों के दौरान, नेटवर्क या डिस्क से डेटा को फिर से फ़ेच करने से बचाता है. ViewModel को लागू करने का तरीका जानने के लिए, ViewModel गाइड देखें.
ViewModel, डेटा को मेमोरी में सेव करता है. इसका मतलब है कि डिस्क या नेटवर्क से डेटा को वापस पाने की तुलना में, इसे वापस पाना सस्ता होता है. ViewModel, किसी ऐक्टिविटी (या लाइफ़साइकल के किसी अन्य मालिक) से जुड़ा होता है. यह कॉन्फ़िगरेशन में बदलाव के दौरान मेमोरी में सेव रहता है. साथ ही, सिस्टम, ViewModel को कॉन्फ़िगरेशन में बदलाव के बाद बनी नई ऐक्टिविटी के इंस्टेंस से अपने-आप जोड़ देता है.
जब उपयोगकर्ता आपकी गतिविधि या फ़्रैगमेंट से बाहर निकलता है या जब finish() को कॉल किया जाता है, तो सिस्टम ViewModels को अपने-आप डिस्ट्रॉय कर देता है. इसका मतलब है कि इन स्थितियों में, उपयोगकर्ता की उम्मीद के मुताबिक स्थिति साफ़ हो जाती है.
सेव की गई इंस्टेंस की स्थिति के उलट, सिस्टम की ओर से शुरू की गई प्रोसेस के बंद होने पर ViewModels डिस्ट्रॉय हो जाते हैं. सिस्टम की वजह से ViewModel में प्रोसेस बंद होने के बाद, डेटा को फिर से लोड करने के लिए SavedStateHandle API का इस्तेमाल करें. इसके अलावा, अगर डेटा यूज़र इंटरफ़ेस (यूआई) से जुड़ा है और उसे ViewModel में सेव करने की ज़रूरत नहीं है, तो onSaveInstanceState() का इस्तेमाल करें. अगर डेटा ऐप्लिकेशन डेटा है, तो उसे डिस्क में सेव करना बेहतर हो सकता है.
अगर आपके पास कॉन्फ़िगरेशन में बदलाव होने पर, यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव करने के लिए पहले से ही कोई इन-मेमोरी समाधान है, तो हो सकता है कि आपको ViewModel का इस्तेमाल न करना पड़े.
सिस्टम की वजह से प्रोसेस बंद होने की समस्या को ठीक करने के लिए, सेव की गई इंस्टेंस की स्थिति को बैकअप के तौर पर इस्तेमाल करना
View सिस्टम में onSaveInstanceState() कॉलबैक और ViewModels में SavedStateHandle, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर की स्थिति को फिर से लोड करने के लिए ज़रूरी डेटा सेव करते हैं. जैसे, अगर सिस्टम किसी ऐक्टिविटी या फ़्रैगमेंट को खत्म कर देता है और बाद में उसे फिर से बनाता है, तो यह डेटा काम आता है. onSaveInstanceState का इस्तेमाल करके, सेव किए गए इंस्टेंस की स्थिति को लागू करने का तरीका जानने के लिए, ऐक्टिविटी के लाइफ़साइकल से जुड़ी गाइड में ऐक्टिविटी की स्थिति को सेव और रीस्टोर करना लेख पढ़ें.
सेव किए गए इंस्टेंस की स्थिति वाले बंडल, कॉन्फ़िगरेशन में होने वाले बदलावों और प्रोसेस के बंद होने के दौरान बने रहते हैं. हालांकि, ये स्टोरेज और स्पीड के हिसाब से सीमित होते हैं, क्योंकि अलग-अलग एपीआई डेटा को क्रम से लगाते हैं. अगर सीरियल किए जा रहे ऑब्जेक्ट जटिल हैं, तो सीरियलाइज़ेशन में बहुत ज़्यादा मेमोरी खर्च हो सकती है. कॉन्फ़िगरेशन में बदलाव के दौरान, यह प्रोसेस मुख्य थ्रेड पर होती है. इसलिए, लंबे समय तक चलने वाले सीरियलाइज़ेशन की वजह से फ़्रेम ड्रॉप हो सकते हैं और विज़ुअल स्टटर हो सकता है.
सेव की गई इंस्टेंस की स्थिति का इस्तेमाल, बड़ी मात्रा में डेटा सेव करने के लिए न करें. जैसे, बिटमैप. साथ ही, ऐसे जटिल डेटा स्ट्रक्चर के लिए भी इसका इस्तेमाल न करें जिन्हें क्रमबद्ध या क्रम से हटाने में ज़्यादा समय लगता है. इसके बजाय, सिर्फ़ प्रिमिटिव टाइप और आसान, छोटे ऑब्जेक्ट सेव करें. जैसे, String. इसलिए, सेव की गई इंस्टेंस की स्थिति का इस्तेमाल करके, ज़रूरी डेटा को कम से कम सेव करें. जैसे, आईडी. इससे, अगर डेटा को सेव रखने के अन्य तरीके काम नहीं करते हैं, तो यूज़र इंटरफ़ेस (यूआई) को उसकी पिछली स्थिति में वापस लाने के लिए ज़रूरी डेटा को फिर से बनाया जा सकता है. ज़्यादातर ऐप्लिकेशन को इसे लागू करना चाहिए, ताकि सिस्टम की ओर से प्रोसेस बंद होने की समस्या को ठीक किया जा सके.
आपके ऐप्लिकेशन के इस्तेमाल के उदाहरणों के आधार पर, हो सकता है कि आपको सेव किए गए इंस्टेंस की स्थिति का इस्तेमाल करने की ज़रूरत न पड़े. उदाहरण के लिए, कोई ब्राउज़र उपयोगकर्ता को ठीक उसी वेबपेज पर वापस ले जा सकता है जिसे वह ब्राउज़र बंद करने से पहले देख रहा था. अगर आपकी गतिविधि इस तरह से काम करती है, तो सेव किए गए इंस्टेंस की स्थिति का इस्तेमाल न करें. इसके बजाय, सभी डेटा को स्थानीय तौर पर सेव करें.
इसके अलावा, किसी इंटेंट से कोई गतिविधि खोलने पर, एक्स्ट्रा का बंडल गतिविधि को तब भी डिलीवर किया जाता है, जब कॉन्फ़िगरेशन में बदलाव होता है और जब सिस्टम गतिविधि को वापस लाता है.
इन दोनों ही स्थितियों में, आपको ViewModel का इस्तेमाल करना चाहिए, ताकि कॉन्फ़िगरेशन में बदलाव के दौरान डेटाबेस से डेटा को फिर से लोड करने में समय बर्बाद न हो.
अगर यूज़र इंटरफ़ेस (यूआई) का डेटा आसान और कम साइज़ का है, तो सेव किए गए इंस्टेंस की स्थिति के एपीआई का इस्तेमाल करके, स्थिति के डेटा को सुरक्षित रखा जा सकता है.
SavedStateRegistry का इस्तेमाल करके, सेव की गई स्थिति में हुक करना
Fragment 1.1.0 या इसकी ट्रांज़िटिव डिपेंडेंसी Activity 1.0.0 से शुरू होने वाले यूज़र इंटरफ़ेस (यूआई) कंट्रोलर, जैसे कि Activity या Fragment, SavedStateRegistryOwner को लागू करते हैं और SavedStateRegistry उपलब्ध कराते हैं, जो उस कंट्रोलर से जुड़ा होता है. SavedStateRegistry की मदद से, कॉम्पोनेंट आपके यूज़र इंटरफ़ेस (यूआई) कंट्रोलर की सेव की गई स्थिति में हुक कर सकते हैं, ताकि वे इसका इस्तेमाल कर सकें या इसमें योगदान दे सकें. उदाहरण के लिए, ViewModel के लिए Saved State मॉड्यूल, SavedStateRegistry का इस्तेमाल करके SavedStateHandle बनाता है और इसे आपके ViewModel ऑब्जेक्ट को उपलब्ध कराता है. getSavedStateRegistry को कॉल करके, अपने यूज़र इंटरफ़ेस (यूआई) कंट्रोलर से SavedStateRegistry को वापस पाया जा सकता है.
सेव की गई स्थिति में योगदान देने वाले कॉम्पोनेंट को SavedStateRegistry.SavedStateProvider लागू करना होगा. यह एक ऐसा तरीका तय करता है जिसे saveState कहा जाता है. saveState() तरीके से, आपका कॉम्पोनेंट एक Bundle दिखाता है. इसमें वह स्थिति शामिल होती है जिसे उस कॉम्पोनेंट से सेव किया जाना चाहिए.
SavedStateRegistry, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर की लाइफ़साइकल के सेविंग स्टेट फ़ेज़ के दौरान इस तरीके को कॉल करता है.
class SearchManager implements SavedStateRegistry.SavedStateProvider {
private static String QUERY = "query";
private String query = null;
...
@NonNull
@Override
public Bundle saveState() {
Bundle bundle = new Bundle();
bundle.putString(QUERY, query);
return bundle;
}
}
SavedStateProvider रजिस्टर करने के लिए, registerSavedStateProvider() पर कॉल करें. साथ ही, सेवा देने वाली कंपनी के डेटा और सेवा देने वाली कंपनी से जोड़ने के लिए एक कुंजी पास करें.SavedStateRegistry सेवा देने वाली कंपनी के लिए पहले से सेव किए गए डेटा को, सेव की गई स्थिति से वापस पाया जा सकता है. इसके लिए, SavedStateRegistry पर consumeRestoredStateForKey() को कॉल करें. साथ ही, सेवा देने वाली कंपनी के डेटा से जुड़ी कुंजी पास करें.
Activity या Fragment में, super.onCreate() को कॉल करने के बाद, onCreate() में SavedStateProvider रजिस्टर किया जा सकता है. इसके अलावा, SavedStateRegistryOwner पर LifecycleObserver सेट किया जा सकता है. इससे LifecycleOwner लागू होता है. साथ ही, ON_CREATE इवेंट होने पर SavedStateProvider को रजिस्टर किया जा सकता है. LifecycleObserver का इस्तेमाल करके, पहले से सेव की गई स्थिति को रजिस्टर करने और वापस पाने की प्रोसेस को SavedStateRegistryOwner से अलग किया जा सकता है.
Kotlin
class SearchManager(registryOwner: SavedStateRegistryOwner) : SavedStateRegistry.SavedStateProvider {
companion object {
private const val PROVIDER = "search_manager"
private const val QUERY = "query"
}
private val query: String? = null
init {
// Register a LifecycleObserver for when the Lifecycle hits ON_CREATE
registryOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_CREATE) {
val registry = registryOwner.savedStateRegistry
// Register this object for future calls to saveState()
registry.registerSavedStateProvider(PROVIDER, this)
// Get the previously saved state and restore it
val state = registry.consumeRestoredStateForKey(PROVIDER)
// Apply the previously saved state
query = state?.getString(QUERY)
}
}
}
override fun saveState(): Bundle {
return bundleOf(QUERY to query)
}
...
}
class SearchFragment : Fragment() {
private var searchManager = SearchManager(this)
...
}
Java
class SearchManager implements SavedStateRegistry.SavedStateProvider {
private static String PROVIDER = "search_manager";
private static String QUERY = "query";
private String query = null;
public SearchManager(SavedStateRegistryOwner registryOwner) {
registryOwner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
if (event == Lifecycle.Event.ON_CREATE) {
SavedStateRegistry registry = registryOwner.getSavedStateRegistry();
// Register this object for future calls to saveState()
registry.registerSavedStateProvider(PROVIDER, this);
// Get the previously saved state and restore it
Bundle state = registry.consumeRestoredStateForKey(PROVIDER);
// Apply the previously saved state
if (state != null) {
query = state.getString(QUERY);
}
}
});
}
@NonNull
@Override
public Bundle saveState() {
Bundle bundle = new Bundle();
bundle.putString(QUERY, query);
return bundle;
}
...
}
class SearchFragment extends Fragment {
private SearchManager searchManager = new SearchManager(this);
...
}
जटिल या बड़े डेटा के लिए, प्रोसेस बंद होने की समस्या को ठीक करने के लिए लोकल परसिस्टेंस का इस्तेमाल करना
स्थानीय स्टोरेज में सेव किया गया डेटा, जैसे कि डेटाबेस या शेयर की गई प्राथमिकताएं, तब तक सेव रहता है, जब तक आपका ऐप्लिकेशन उपयोगकर्ता के डिवाइस पर इंस्टॉल रहता है. हालांकि, अगर उपयोगकर्ता आपके ऐप्लिकेशन का डेटा मिटा देता है, तो यह डेटा मिट जाता है. इस तरह की लोकल स्टोरेज, सिस्टम की ओर से शुरू की गई गतिविधि और ऐप्लिकेशन प्रोसेस के बंद होने के बाद भी बनी रहती है. हालांकि, इसे वापस पाना महंगा पड़ सकता है, क्योंकि इसे लोकल स्टोरेज से मेमोरी में पढ़ना होगा. अक्सर, यह परसिस्टेंट लोकल स्टोरेज पहले से ही आपके ऐप्लिकेशन के आर्किटेक्चर का हिस्सा हो सकता है. इसका इस्तेमाल, उस डेटा को सेव करने के लिए किया जाता है जिसे आपको ऐक्टिविटी खोलने और बंद करने पर भी सेव रखना है.
ViewModel और सेव की गई इंस्टेंस की स्थिति, दोनों ही लंबे समय तक डेटा सेव करने के समाधान नहीं हैं. इसलिए, ये लोकल स्टोरेज के विकल्प नहीं हैं. जैसे, कोई डेटाबेस. इसके बजाय, आपको इन तरीकों का इस्तेमाल सिर्फ़ यूज़र इंटरफ़ेस (यूआई) की मौजूदा स्थिति को कुछ समय के लिए सेव करने के लिए करना चाहिए. साथ ही, ऐप्लिकेशन के अन्य डेटा के लिए हमेशा मौजूद रहने वाले स्टोरेज का इस्तेमाल करना चाहिए. अपने ऐप्लिकेशन मॉडल के डेटा को लंबे समय तक बनाए रखने के लिए, लोकल स्टोरेज का इस्तेमाल कैसे करें, इस बारे में ज़्यादा जानने के लिए ऐप्लिकेशन आर्किटेक्चर की गाइड देखें. उदाहरण के लिए, डिवाइस को रीस्टार्ट करने पर भी डेटा बना रहता है.
यूज़र इंटरफ़ेस की स्थिति को मैनेज करना: बांटो और जीतो
अलग-अलग तरह के परसिस्टेंस मैकेनिज़्म के बीच काम को बांटकर, यूज़र इंटरफ़ेस (यूआई) की स्थिति को आसानी से सेव और वापस लाया जा सकता है. ज़्यादातर मामलों में, इन सभी तरीकों को गतिविधि में इस्तेमाल किया गया अलग-अलग तरह का डेटा सेव करना चाहिए. यह डेटा की जटिलता, ऐक्सेस करने की स्पीड, और लाइफ़टाइम के ट्रेड-ऑफ़ पर आधारित होना चाहिए:
- लोकल परसिस्टेंस: यह ऐप्लिकेशन के उस डेटा को सेव करता है जिसे आपको मिटाना नहीं है. ऐसा तब होता है, जब गतिविधि को खोला और बंद किया जाता है.
- उदाहरण: गानों के ऑब्जेक्ट का कलेक्शन. इसमें ऑडियो फ़ाइलें और मेटाडेटा शामिल हो सकता है.
ViewModel: यह कुकी, यूज़र इंटरफ़ेस (यूआई) दिखाने के लिए ज़रूरी सभी डेटा को मेमोरी में सेव करती है. इसे स्क्रीन यूज़र इंटरफ़ेस (यूआई) की स्थिति कहा जाता है.- उदाहरण: हाल ही की खोज के गाने के ऑब्जेक्ट और हाल ही की सर्च क्वेरी.
- सेव की गई इंस्टेंस की स्थिति: यह कुकी, यूज़र इंटरफ़ेस (यूआई) की स्थिति को फिर से लोड करने के लिए ज़रूरी डेटा को सेव करती है. ऐसा तब होता है, जब सिस्टम बंद हो जाता है और फिर यूज़र इंटरफ़ेस (यूआई) को फिर से बनाता है. यहां जटिल ऑब्जेक्ट सेव करने के बजाय, उन्हें लोकल स्टोरेज में सेव करें. साथ ही, सेव किए गए इंस्टेंस की स्थिति वाले एपीआई में इन ऑब्जेक्ट के लिए यूनीक आईडी सेव करें.
- उदाहरण: हाल ही में की गई सर्च क्वेरी को सेव करना.
उदाहरण के लिए, ऐसी गतिविधि पर विचार करें जिससे आपको गानों की लाइब्रेरी में खोजने की सुविधा मिलती है. यहां बताया गया है कि अलग-अलग इवेंट को कैसे हैंडल किया जाना चाहिए:
जब उपयोगकर्ता कोई गाना जोड़ता है, तो ViewModel तुरंत इस डेटा को स्थानीय तौर पर सेव करने का काम सौंप देता है. अगर इस नए गाने को यूज़र इंटरफ़ेस (यूआई) में दिखाना है, तो आपको ViewModel ऑब्जेक्ट में मौजूद डेटा को भी अपडेट करना होगा, ताकि गाने को जोड़ा जा सके. ध्यान रखें कि डेटाबेस में सभी इंसर्ट, मुख्य थ्रेड से बाहर किए जाएं.
जब उपयोगकर्ता किसी गाने को खोजता है, तो डेटाबेस से लोड किए गए गाने के जटिल डेटा को स्क्रीन यूज़र इंटरफ़ेस (यूआई) की स्थिति के हिस्से के तौर पर, ViewModel ऑब्जेक्ट में तुरंत सेव किया जाना चाहिए.
जब गतिविधि बैकग्राउंड में चली जाती है और सिस्टम, सेव किए गए इंस्टेंस की स्थिति वाले एपीआई को कॉल करता है, तो खोज क्वेरी को सेव किए गए इंस्टेंस की स्थिति में सेव किया जाना चाहिए. ऐसा तब किया जाना चाहिए, जब प्रोसेस फिर से बनाई जाती है. इस ऐप्लिकेशन में सेव किए गए डेटा को लोड करने के लिए, यह जानकारी ज़रूरी है. इसलिए, सर्च क्वेरी को ViewModel SavedStateHandle में सेव करें. डेटा लोड करने और यूज़र इंटरफ़ेस (यूआई) को उसकी मौजूदा स्थिति में वापस लाने के लिए, आपको इस जानकारी की ज़रूरत होगी.
जटिल स्थितियों को पहले जैसा करना: टुकड़ों को फिर से जोड़ना
जब उपयोगकर्ता को गतिविधि पर वापस जाना होता है, तो गतिविधि को फिर से बनाने के लिए दो संभावित स्थितियां होती हैं:
- सिस्टम के बंद करने के बाद, गतिविधि को फिर से बनाया जाता है. सिस्टम ने क्वेरी को सेव किए गए इंस्टेंस की स्थिति वाले बंडल में सेव किया है. साथ ही, अगर
SavedStateHandleका इस्तेमाल नहीं किया जाता है, तो यूज़र इंटरफ़ेस (यूआई) को क्वेरी कोViewModelपर पास करना चाहिए.ViewModelको पता चलता है कि खोज के नतीजे कैश मेमोरी में सेव नहीं किए गए हैं. इसलिए, वह दी गई खोज क्वेरी का इस्तेमाल करके, खोज के नतीजे लोड करने का काम किसी और को सौंप देता है. - कॉन्फ़िगरेशन में बदलाव होने के बाद, ऐक्टिविटी को फिर से बनाया जाता है.
ViewModelइंस्टेंस को डिस्ट्रॉय नहीं किया गया है. इसलिए,ViewModelके पास मेमोरी में कैश मेमोरी में सेव की गई पूरी जानकारी है. इसलिए, इसे डेटाबेस को फिर से क्वेरी करने की ज़रूरत नहीं है.
अन्य संसाधन
यूज़र इंटरफ़ेस (यूआई) की स्थितियों को सेव करने के बारे में ज़्यादा जानने के लिए, यहां दिए गए संसाधन देखें.
ब्लॉग
- ViewModels: एक आसान उदाहरण
- ViewModels: Persistence,
onSaveInstanceState, Restoring UI State and Loaders