कॉन्फ़िगरेशन में हुए बदलावों को हैंडल करना (व्यू)

सिद्धांत और Jetpack Compose को लागू करना

ऐप्लिकेशन के चालू होने पर, डिवाइस के कुछ कॉन्फ़िगरेशन बदले जा सकते हैं. इनमें यहां दिए गए कॉन्टेंट के अलावा, और भी कई तरह का कॉन्टेंट शामिल है:

  • ऐप्लिकेशन का डिसप्ले साइज़
  • स्क्रीन की दिशा
  • फ़ॉन्ट का साइज़ और मोटाई
  • स्थान-भाषा
  • गहरे रंग वाले मोड बनाम हल्के रंग वाला मोड
  • कीबोर्ड उपलब्ध है या नहीं

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

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

गतिविधि को फिर से शुरू करना

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

फिर से बनाने की सुविधा, आपके ऐप्लिकेशन को नए कॉन्फ़िगरेशन के हिसाब से ढालने में मदद करती है. इसके लिए, यह सुविधा आपके ऐप्लिकेशन को उन वैकल्पिक संसाधनों के साथ अपने-आप रिलोड करती है जो डिवाइस के नए कॉन्फ़िगरेशन से मेल खाते हैं.

रीक्रिएशन का उदाहरण

ऐसी TextView के बारे में सोचें जो लेआउट एक्सएमएल फ़ाइल में तय किए गए android:text="@string/title" का इस्तेमाल करके, एक स्टैटिक टाइटल दिखाती है. व्यू बनाने पर, यह मौजूदा भाषा के आधार पर टेक्स्ट को सिर्फ़ एक बार सेट करता है. भाषा बदलने पर, सिस्टम गतिविधि को फिर से बनाता है. इसलिए, सिस्टम व्यू को फिर से बनाता है और नई भाषा के आधार पर, उसे सही वैल्यू पर सेट करता है.

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

उपयोगकर्ताओं की उम्मीदें

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

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

  • डिवाइस को घुमाना
  • मल्टी-विंडो मोड में जाना
  • मल्टी-विंडो मोड या फ़्री-फ़ॉर्म विंडो में ऐप्लिकेशन का साइज़ बदलना
  • एक से ज़्यादा डिसप्ले वाले फ़ोल्डेबल डिवाइस को फ़ोल्ड करना
  • सिस्टम की थीम बदलना, जैसे कि गहरे रंग वाला मोड बनाम हल्के रंग वाला मोड
  • फ़ॉन्ट का साइज़ बदलना
  • सिस्टम या ऐप्लिकेशन की भाषा बदलना
  • हार्डवेयर कीबोर्ड को कनेक्ट या डिसकनेक्ट करना
  • डॉक को कनेक्ट या डिसकनेक्ट करना

Activity को फिर से बनाने के दौरान, काम की स्थिति को बनाए रखने के लिए तीन मुख्य तरीके अपनाए जा सकते हैं. आपको किस तरह की स्थिति बनाए रखनी है, इसके आधार पर तय करें कि आपको कौनसी कुकी इस्तेमाल करनी है:

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

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

व्यू सिस्टम में कॉन्फ़िगरेशन में हुए बदलावों पर प्रतिक्रिया देना

View सिस्टम में, जब कॉन्फ़िगरेशन में कोई ऐसा बदलाव होता है जिसके लिए आपने Activity को फिर से बनाने की सुविधा बंद की है, तब गतिविधि को Activity.onConfigurationChanged पर कॉल मिलता है. अटैच किए गए सभी व्यू को भी View.onConfigurationChanged पर कॉल मिलता है. कॉन्फ़िगरेशन में हुए ऐसे बदलावों के लिए जिन्हें आपने android:configChanges में नहीं जोड़ा है, सिस्टम सामान्य तरीके से गतिविधि को फिर से बनाता है.

onConfigurationChanged कॉलबैक तरीके को Configuration ऑब्जेक्ट मिलता है. यह ऑब्जेक्ट, डिवाइस के नए कॉन्फ़िगरेशन के बारे में बताता है. Configuration ऑब्जेक्ट में मौजूद फ़ील्ड पढ़ें, ताकि आपको पता चल सके कि नया कॉन्फ़िगरेशन क्या है. इसके बाद के बदलाव करने के लिए, अपने इंटरफ़ेस में इस्तेमाल किए गए संसाधनों को अपडेट करें. जब सिस्टम इस तरीके को कॉल करता है, तब आपकी गतिविधि के Resources ऑब्जेक्ट को अपडेट किया जाता है, ताकि नए कॉन्फ़िगरेशन के आधार पर संसाधन दिखाए जा सकें. इससे, सिस्टम आपकी गतिविधि को रीस्टार्ट किए बिना, यूज़र इंटरफ़ेस (यूआई) के एलिमेंट रीसेट किए जा सकते हैं.

उदाहरण के लिए, onConfigurationChanged लागू करने की यहां दी गई जांच से यह पता चलता है कि कीबोर्ड उपलब्ध है या नहीं:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
    } else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
    }
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
    } else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
    }
}

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

स्थिति बनाए रखें

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

  • ज़रूरी बदलाव: कॉन्फ़िगरेशन में ऐसे बदलाव किए जा सकते हैं जिन्हें रोका नहीं जा सकता. इनकी वजह से, आपका ऐप्लिकेशन रीस्टार्ट हो सकता है.
  • ऐप्लिकेशन की प्रोसेस बंद होना: आपका ऐप्लिकेशन, सिस्टम की वजह से ऐप्लिकेशन की प्रोसेस बंद होने की समस्या को ठीक कर सकता हो. अगर उपयोगकर्ता आपके ऐप्लिकेशन को छोड़कर किसी दूसरे ऐप्लिकेशन पर चला जाता है और आपका ऐप्लिकेशन बैकग्राउंड में चला जाता है, तो सिस्टम ऐप्लिकेशन को बंद कर सकता है.

कॉन्फ़िगरेशन में बदलाव: मुख्य सिद्धांत और सबसे सही तरीके

कॉन्फ़िगरेशन में बदलाव करते समय, आपको इन मुख्य बातों के बारे में पता होना चाहिए:

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

उपयोगकर्ताओं को बेहतर अनुभव देने के लिए, यहां दिए गए सबसे सही तरीके अपनाएं:

  • कॉन्फ़िगरेशन में बार-बार होने वाले बदलावों के लिए तैयार रहें: यह न मान लें कि कॉन्फ़िगरेशन में बदलाव कभी-कभार होते हैं या कभी नहीं होते. भले ही, एपीआई लेवल, फ़ॉर्म फ़ैक्टर या यूज़र इंटरफ़ेस (यूआई) टूलकिट कुछ भी हो. जब कोई उपयोगकर्ता कॉन्फ़िगरेशन में बदलाव करता है, तो वह उम्मीद करता है कि ऐप्लिकेशन अपडेट हो जाएं और नए कॉन्फ़िगरेशन के साथ सही तरीके से काम करते रहें.
  • स्टेट बनाए रखना: Activity को फिर से बनाने पर, उपयोगकर्ता की स्टेट न बदले. यूज़र इंटरफ़ेस (यूआई) की स्थितियां सेव करना में बताए गए तरीके से, स्थिति को बनाए रखें.
  • समस्या को तुरंत ठीक करने के लिए, ऑप्ट आउट न करें: स्टेट के नुकसान से बचने के लिए, Activity रीक्रिएशन से ऑप्ट आउट न करें. गतिविधि को फिर से बनाने की सुविधा से ऑप्ट आउट करने के लिए, आपको बदलाव को मैनेज करने का वादा पूरा करना होगा. हालांकि, कॉन्फ़िगरेशन में किए गए अन्य बदलावों, प्रोसेस के बंद होने या ऐप्लिकेशन को बंद करने की वजह से, आपको अब भी Activity को फिर से बनाना पड़ सकता है. Activity को फिर से बनाने की सुविधा को पूरी तरह से बंद नहीं किया जा सकता. यूज़र इंटरफ़ेस (यूआई) की स्थितियां सेव करना में बताए गए तरीके से, स्थिति को बनाए रखें.
  • कॉन्फ़िगरेशन में बदलाव करने से न बचें: ओरिएंटेशन, आसपेक्ट रेशियो या साइज़ बदलने की सुविधा पर पाबंदियां न लगाएं, ताकि कॉन्फ़िगरेशन में बदलाव करने और Activity को फिर से बनाने से बचा जा सके. इससे उन लोगों पर बुरा असर पड़ता है जो आपके ऐप्लिकेशन का इस्तेमाल अपनी पसंद के हिसाब से करना चाहते हैं.

साइज़ के आधार पर कॉन्फ़िगरेशन में हुए बदलावों को हैंडल करना

साइज के आधार पर कॉन्फ़िगरेशन में बदलाव कभी भी हो सकते हैं. ऐसा तब होने की संभावना ज़्यादा होती है, जब आपका ऐप्लिकेशन बड़ी स्क्रीन वाले डिवाइस पर चलता हो. ऐसे डिवाइसों पर, उपयोगकर्ता मल्टी-विंडो मोड में काम कर सकते हैं. उन्हें उम्मीद होती है कि आपका ऐप्लिकेशन उस एनवायरमेंट में ठीक से काम करेगा.

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

साइज़ के आधार पर कॉन्फ़िगरेशन में होने वाले बदलावों के लिए, गतिविधि को फिर से बनाने की सुविधा को सीमित करें

साइज़ के आधार पर कॉन्फ़िगरेशन में बदलाव करने के लिए, Activity फिर से बनाने की सुविधा बंद करने पर, सिस्टम Activity को फिर से नहीं बनाता है. इसके बजाय, उसे Activity.onConfigurationChanged पर कॉल आता है. अटैच किए गए सभी व्यू को View.onConfigurationChanged पर कॉल करने का विकल्प मिलता है.

Activity को फिर से बनाने की सुविधा, साइज़ के आधार पर कॉन्फ़िगरेशन में किए गए बदलावों के लिए बंद कर दी जाती है. ऐसा तब होता है, जब आपकी मेनिफ़ेस्ट फ़ाइल में android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" मौजूद हो.

साइज़ के आधार पर कॉन्फ़िगरेशन में हुए बदलावों के लिए, गतिविधि को फिर से बनाने की अनुमति दें

Android 7.0 (एपीआई लेवल 24) और इसके बाद के वर्शन पर, साइज़ के आधार पर कॉन्फ़िगरेशन में बदलाव होने पर, Activity फिर से बनाना सिर्फ़ तब होता है, जब साइज़ में काफ़ी बदलाव हुआ हो. जब सिस्टम, साइज़ पूरा न होने की वजह से Activity को फिर से नहीं बनाता है, तो सिस्टम Activity.onConfigurationChanged और View.onConfigurationChanged को कॉल कर सकता है.

Activity को फिर से नहीं बनाने पर, Activity और View कॉलबैक से जुड़ी कुछ चेतावनियों का ध्यान रखना होगा:

  • Android 11 (एपीआई लेवल 30) से लेकर Android 13 (एपीआई लेवल 33) तक, Activity.onConfigurationChanged को कॉल नहीं किया जाता.
  • एक जानी-पहचानी समस्या है. इसमें Android 12L (एपीआई लेवल 32) और Android 13 (एपीआई लेवल 33) के शुरुआती वर्शन पर, कुछ मामलों में View.onConfigurationChanged को कॉल नहीं किया जा सकता. ज़्यादा जानकारी के लिए, यह सार्वजनिक समस्या देखें. इस समस्या को Android 13 के बाद के वर्शन और Android 14 में ठीक कर दिया गया है.

ऐसे कोड के लिए जो साइज़ के आधार पर कॉन्फ़िगरेशन में होने वाले बदलावों को सुनने पर निर्भर करता है, हमारा सुझाव है कि Activity को फिर से बनाने या Activity.onConfigurationChanged पर भरोसा करने के बजाय, View का इस्तेमाल करें. इसमें View.onConfigurationChanged को बदल दिया गया है.