कॉन्फ़िगरेशन के बदलावों को हैंडल करना

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

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

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

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

Activity को फिर से बनाना

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

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

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

फिर से बनाने का उदाहरण

मान लें कि एक कंपोज़ेबल, स्ट्रिंग रिसॉर्स का इस्तेमाल करके स्टैटिक टाइटल दिखाता है:

// In the res/values/strings.xml file
// <string name="compose">Jetpack Compose</string>

// In your Compose code
Text(
    text = stringResource(R.string.compose)
)

Activity बनाने पर, Text कंपोज़ेबल, मौजूदा कॉन्फ़िगरेशन (जैसे, भाषा) को पढ़ता है और सही स्ट्रिंग रिसॉर्स को रिज़ॉल्व करता है.

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

फिर से बनाने की प्रोसेस में, Activity में फ़ील्ड के तौर पर सेव की गई कोई भी स्थिति मिट जाती है.

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

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

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

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

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

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

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

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

ऐक्टिविटी को फिर से बनाने की प्रोसेस को सीमित करना

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

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

Compose में कॉन्फ़िगरेशन में हुए बदलावों को सीधे तौर पर हैंडल करने के कई फ़ायदे हैं:

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

खास कॉन्फ़िगरेशन में बदलाव होने पर, ऐक्टिविटी को फिर से बनाने की प्रोसेस को बंद करने के लिए, android:configChanges में कॉन्फ़िगरेशन का टाइप जोड़ें. <activity> एंट्री में अपनी AndroidManifest.xml फ़ाइल में. `android:configChanges` एट्रिब्यूट के दस्तावेज़ में, संभावित वैल्यू दिखती हैं.

यहां दिए गए मेनिफ़ेस्ट कोड में, Activity को फिर से बनाने की प्रोसेस को बंद किया गया है, MyActivityजब स्क्रीन ओरिएंटेशन और कीबोर्ड की उपलब्धता में बदलाव होता है:

<activity
    android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
    android:label="@string/app_name">

Android 17

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

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

<activity
    android:name=".MyActivity"
    android:recreateOnConfigChanges="keyboard|keyboardHidden|navigation|colorMode|touchscreen|...">
    ...
</activity>

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

Jetpack Compose की मदद से, आपका ऐप्लिकेशन कॉन्फ़िगरेशन में हुए बदलावों पर ज़्यादा आसानी से प्रतिक्रिया दे सकता है. हालांकि, अगर आपने उन सभी कॉन्फ़िगरेशन में बदलाव होने पर, Activity को फिर से बनाने की प्रोसेस को बंद कर दिया है जहां ऐसा किया जा सकता है, तो भी आपके ऐप्लिकेशन को कॉन्फ़िगरेशन में हुए बदलावों को सही तरीके से हैंडल करना होगा.

Configuration ऑब्जेक्ट, Compose यूज़र इंटरफ़ेस (यूआई) के क्रम में LocalConfiguration कंपोज़िशन लोकल के साथ उपलब्ध है. जब भी इसमें बदलाव होता है, तो LocalConfiguration.current से पढ़ने वाले कंपोज़ेबल फ़ंक्शन फिर से कंपोज़ होते हैं. कंपोज़िशन लोकल कैसे काम करते हैं, इस बारे में जानने के लिए, CompositionLocal की मदद से स्थानीय तौर पर स्कोप किया गया डेटा लेख पढ़ें.

उदाहरण

यहां दिए गए उदाहरण में, एक कंपोज़ेबल, खास फ़ॉर्मैट में तारीख दिखाता है. यह कंपोज़ेबल, LocalConfiguration.current के साथ ConfigurationCompat.getLocales को कॉल करके, सिस्टम की स्थानीय भाषा के कॉन्फ़िगरेशन में हुए बदलावों पर प्रतिक्रिया देता है.

@Composable
fun DateText(year: Int, dayOfYear: Int) {
    val dateTimeFormatter = DateTimeFormatter.ofPattern(
        "MMM dd",
        ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
    )
    Text(
        dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
    )
}

स्थानीय भाषा बदलने पर, Activity को फिर से बनाने की प्रोसेस से बचने के लिए, Compose कोड को होस्ट करने वाली Activity को स्थानीय भाषा के कॉन्फ़िगरेशन में हुए बदलावों से ऑप्ट आउट करना होगा. ऐसा करने के लिए, android:configChanges को locale|layoutDirection पर सेट करें.

कॉन्फ़िगरेशन में बदलाव: ज़रूरी कॉन्सेप्ट और सबसे सही तरीके

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

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

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

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

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

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

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

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

साइज़ के हिसाब से कॉन्फ़िगरेशन में बदलाव होने पर, Activity को फिर से बनाने की प्रोसेस को बंद करने पर, सिस्टम Activity को फिर से नहीं बनाता. इसके बजाय, इसे Activity.onConfigurationChanged पर कॉल मिलता है. LocalConfiguration.current को पढ़ने वाले सभी कंपोज़ेबल, नए साइज़ को दिखाने के लिए अपने-आप फिर से कंपोज़ हो जाते हैं.

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

अन्य संसाधन

कॉन्फ़िगरेशन में हुए बदलावों को हैंडल करने के बारे में ज़्यादा जानने के लिए, ये अन्य संसाधन देखें:

दस्तावेज़

Views का कॉन्टेंट