Android Kotlin Fundamentals 04.2: Complex lifecycle situations

यह कोडलैब, Android Kotlin Fundamentals कोर्स का हिस्सा है. अगर कोडलैब को क्रम से पूरा किया जाता है, तो आपको इस कोर्स से सबसे ज़्यादा फ़ायदा मिलेगा. कोर्स के सभी कोडलैब, Android Kotlin Fundamentals कोडलैब के लैंडिंग पेज पर दिए गए हैं.

शुरुआती जानकारी

पिछले कोडलैब में, आपने Activity और Fragment के लाइफ़साइकल के बारे में जाना था. साथ ही, आपने उन तरीकों के बारे में जाना था जिन्हें गतिविधि और फ़्रैगमेंट में लाइफ़साइकल की स्थिति बदलने पर कॉल किया जाता है. इस कोडलैब में, गतिविधि के लाइफ़साइकल के बारे में ज़्यादा जानकारी दी गई है. आपको Android Jetpack की लाइफ़साइकल लाइब्रेरी के बारे में भी जानकारी मिलती है. यह लाइब्रेरी, लाइफ़साइकल इवेंट को मैनेज करने में आपकी मदद कर सकती है. इसके लिए, आपको बेहतर तरीके से व्यवस्थित किया गया कोड लिखना होगा, जिसे बनाए रखना आसान हो.

आपको पहले से क्या पता होना चाहिए

  • गतिविधि क्या होती है और इसे अपने ऐप्लिकेशन में कैसे बनाया जाता है.
  • Activity और Fragment के लाइफ़साइकल के बारे में बुनियादी जानकारी. साथ ही, उन कॉलबैक के बारे में जानकारी जो किसी गतिविधि के एक से दूसरी स्थिति में जाने पर शुरू होते हैं.
  • गतिविधि या फ़्रैगमेंट लाइफ़साइकल में अलग-अलग समय पर कार्रवाइयां करने के लिए, onCreate() और onStop() लाइफ़साइकल कॉलबैक मैथड को कैसे बदलें.

आपको क्या सीखने को मिलेगा

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

आपको क्या करना होगा

  • DessertClicker ऐप्लिकेशन में टाइमर फ़ंक्शन शामिल करने के लिए, उसमें बदलाव करें. साथ ही, गतिविधि की लाइफ़साइकल में अलग-अलग समय पर टाइमर को शुरू और बंद करें.
  • Android लाइफ़साइकल लाइब्रेरी का इस्तेमाल करने के लिए, ऐप्लिकेशन में बदलाव करें. साथ ही, DessertTimer क्लास को लाइफ़साइकल ऑब्ज़र्वर में बदलें.
  • Android डीबग ब्रिज (adb) को सेट अप करें और उसका इस्तेमाल करें. इससे, ऐप्लिकेशन की प्रोसेस बंद होने और उसके बाद होने वाले लाइफ़साइकल कॉलबैक को सिम्युलेट किया जा सकता है.
  • ऐप्लिकेशन के अचानक बंद होने पर, ऐप्लिकेशन का डेटा खो सकता है. इसलिए, ऐप्लिकेशन का डेटा बनाए रखने के लिए, onSaveInstanceState() तरीके का इस्तेमाल करें. ऐप्लिकेशन फिर से शुरू होने पर, उस डेटा को वापस लाने के लिए कोड जोड़ें.

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

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

पहला चरण: DessertTimer सेट अप करना

  1. पिछले कोडलैब से DessertClicker ऐप्लिकेशन खोलें. (अगर आपके पास ऐप्लिकेशन नहीं है, तो DessertClickerLogs को यहां से डाउनलोड करें.)
  2. प्रोजेक्ट व्यू में, java > com.example.android.dessertclicker को बड़ा करें और DessertTimer.kt खोलें. ध्यान दें कि फ़िलहाल पूरे कोड पर टिप्पणी की गई है, इसलिए यह ऐप्लिकेशन के हिस्से के तौर पर नहीं चलता.
  3. एडिटर विंडो में मौजूद पूरा कोड चुनें. कोड > लाइन वाली टिप्पणी के साथ टिप्पणी करें चुनें या Control+/ (Mac पर Command+/) दबाएं. इस कमांड से, फ़ाइल में मौजूद सभी कोड से टिप्पणी हटाने का विकल्प मिलता है. (Android Studio, ऐप्लिकेशन को फिर से बनाने तक, हल न की गई रेफ़रंस से जुड़ी गड़बड़ियां दिखा सकता है.)
  4. ध्यान दें कि DessertTimer क्लास में startTimer() और stopTimer() शामिल हैं. ये टाइमर को शुरू और बंद करते हैं. startTimer() के चालू होने पर, टाइमर हर सेकंड एक लॉग मैसेज प्रिंट करता है. इसमें टाइमर के चालू होने के बाद से अब तक के कुल सेकंड की संख्या होती है. इसके बाद, stopTimer() तरीके से टाइमर और लॉग स्टेटमेंट बंद हो जाते हैं.
  1. MainActivity.kt खोलें. क्लास में सबसे ऊपर, dessertsSold वैरिएबल के ठीक नीचे, टाइमर के लिए एक वैरिएबल जोड़ें:
private lateinit var dessertTimer : DessertTimer;
  1. नीचे की ओर स्क्रोल करके onCreate() पर जाएं. इसके बाद, setOnClickListener() को कॉल करने के ठीक बाद, नया DessertTimer ऑब्जेक्ट बनाएं:
dessertTimer = DessertTimer()


अब आपके पास डेज़र्ट टाइमर ऑब्जेक्ट है. सोचें कि आपको टाइमर को कहाँ से शुरू और बंद करना चाहिए, ताकि यह सिर्फ़ तब चले, जब गतिविधि स्क्रीन पर हो. अगले चरणों में, कुछ विकल्पों के बारे में बताया गया है.

दूसरा चरण: टाइमर शुरू और बंद करना

onStart() तरीके को तब कॉल किया जाता है, जब गतिविधि दिखने वाली होती है. onStop() तरीके को तब कॉल किया जाता है, जब गतिविधि दिखना बंद हो जाती है. ये कॉलबैक, टाइमर को शुरू और बंद करने के लिए सही विकल्प हैं.

  1. MainActivity क्लास में, onStart() कॉलबैक में टाइमर शुरू करें:
override fun onStart() {
   super.onStart()
   dessertTimer.startTimer()

   Timber.i("onStart called")
}
  1. टाइमर को onStop():
    पर बंद करो
override fun onStop() {
   super.onStop()
   dessertTimer.stopTimer()

   Timber.i("onStop Called")
}
  1. ऐप्लिकेशन को कंपाइल और चलाएं. Android Studio में, Logcat पैन पर क्लिक करें. Logcat के खोज बॉक्स में, dessertclicker डालें. इससे MainActivity और DessertTimer, दोनों क्लास के हिसाब से फ़िल्टर हो जाएगा. ध्यान दें कि ऐप्लिकेशन शुरू होते ही, टाइमर भी तुरंत शुरू हो जाता है.
  2. वापस जाएं बटन पर क्लिक करें. आपको दिखेगा कि टाइमर फिर से रुक गया है. टाइमर बंद हो जाता है, क्योंकि गतिविधि और उसे कंट्रोल करने वाले टाइमर, दोनों को बंद कर दिया गया है.
  3. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन वाली स्क्रीन का इस्तेमाल करें. Logcat में देखें कि टाइमर 0 से फिर से शुरू हो गया है.
  4. शेयर करें बटन पर क्लिक करें. Logcat में देखें कि टाइमर अब भी चल रहा है.

  5. होम बटन पर क्लिक करें. Logcat में सूचना दें कि टाइमर चलना बंद हो गया है.
  6. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन वाली स्क्रीन का इस्तेमाल करें. Logcat में देखें कि टाइमर वहीं से फिर से शुरू हो गया है जहां वह रुका था.
  7. MainActivity में, onStop() तरीके में, stopTimer() को कॉल करने वाले कोड को टिप्पणी के तौर पर मार्क करें. stopTimer() को टिप्पणी के तौर पर मार्क करने से, यह पता चलता है कि आपने onStart() में कोई कार्रवाई शुरू की है, लेकिन onStop() में उसे बंद करना भूल गए हैं.
  8. ऐप्लिकेशन को कंपाइल और रन करें. इसके बाद, टाइमर शुरू होने पर होम बटन पर क्लिक करें. ऐप्लिकेशन के बैकग्राउंड में होने के बावजूद, टाइमर चालू रहता है और सिस्टम के संसाधनों का लगातार इस्तेमाल करता है. टाइमर को चालू रखना, आपके ऐप्लिकेशन के लिए मेमोरी लीक की समस्या है. साथ ही, ऐसा हो सकता है कि आप ऐसा न चाहें.

    सामान्य तौर पर, जब किसी कॉलबैक में कुछ सेट अप या शुरू किया जाता है, तो उससे जुड़े कॉलबैक में उसे बंद या हटाया जाता है. इस तरह, ज़रूरत न होने पर कोई भी प्रोसेस अपने-आप बंद हो जाती है.
  1. onStop() में उस लाइन से टिप्पणी हटाएं जहाँ आपको टाइमर रोकना है.
  2. startTimer() को onStart() से काटकर, onCreate() में चिपकाएं. इस बदलाव से पता चलता है कि onCreate() में किसी संसाधन को शुरू करने और उसे शुरू करने के लिए, onCreate() का इस्तेमाल करने के बजाय, onCreate() का इस्तेमाल किया जाता है.onStart()
  3. ऐप्लिकेशन को कंपाइल और चलाएं. ध्यान दें कि टाइमर शुरू हो गया है, जैसा कि आपने उम्मीद की थी.
  4. ऐप्लिकेशन को बंद करने के लिए, होम पर क्लिक करें. टाइमर बंद हो जाता है.
  5. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन की स्क्रीन का इस्तेमाल करें. ध्यान दें कि इस मामले में टाइमर फिर से शुरू नहीं होता, क्योंकि onCreate() को सिर्फ़ तब कॉल किया जाता है, जब ऐप्लिकेशन शुरू होता है. जब कोई ऐप्लिकेशन फ़ोरग्राउंड में वापस आता है, तब इसे कॉल नहीं किया जाता.

इन बातों का ध्यान रखें:

  • लाइफ़साइकल कॉलबैक में किसी संसाधन को सेट अप करने के साथ-साथ, उसे बंद भी करें.
  • सेटअप और टियरडाउन को उनसे जुड़े तरीकों में करें.
  • अगर आपने onStart() में कोई सुविधा सेट अप की है, तो उसे onStop() में जाकर बंद करें या फिर से हटा दें.

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

ज़्यादा जटिल Android ऐप्लिकेशन में, onStart() या onCreate() में कई चीज़ें सेट अप की जा सकती हैं. इसके बाद, onStop() या onDestroy() में उन सभी को हटाया जा सकता है. उदाहरण के लिए, आपके पास ऐसे ऐनिमेशन, संगीत, सेंसर या टाइमर हो सकते हैं जिन्हें आपको सेट अप और बंद करना होता है. साथ ही, उन्हें शुरू और बंद करना होता है. अगर इनमें से कोई भी काम नहीं किया जाता है, तो बग और समस्याएं आ सकती हैं.

लाइफ़साइकल लाइब्रेरी, इस टास्क को आसान बनाती है. यह Android Jetpack का हिस्सा है. यह लाइब्रेरी उन मामलों में खास तौर पर काम आती है जहां आपको कई मूविंग पार्ट को ट्रैक करना होता है. इनमें से कुछ अलग-अलग लाइफ़साइकल स्टेट में होते हैं. यह लाइब्रेरी, लाइफ़साइकल के काम करने के तरीके को बदल देती है: आम तौर पर, ऐक्टिविटी या फ़्रैगमेंट, किसी कॉम्पोनेंट (जैसे कि DessertTimer) को यह बताता है कि लाइफ़साइकल कॉलबैक होने पर क्या करना है. हालांकि, लाइफ़साइकल लाइब्रेरी का इस्तेमाल करने पर, कॉम्पोनेंट खुद ही लाइफ़साइकल में होने वाले बदलावों पर नज़र रखता है. इसके बाद, बदलाव होने पर ज़रूरी कार्रवाई करता है.

लाइफ़साइकल लाइब्रेरी के तीन मुख्य हिस्से होते हैं:

  • लाइफ़साइकल के मालिक. ये ऐसे कॉम्पोनेंट होते हैं जिनके पास लाइफ़साइकल होती है. इसलिए, ये लाइफ़साइकल के "मालिक" होते हैं. Activity और Fragment, लाइफ़साइकल के मालिक हैं. लाइफ़साइकल के मालिक, LifecycleOwner इंटरफ़ेस को लागू करते हैं.
  • Lifecycle क्लास, जो लाइफ़साइकल के मालिक की मौजूदा स्थिति को बनाए रखती है. साथ ही, लाइफ़साइकल में बदलाव होने पर इवेंट ट्रिगर करती है.
  • लाइफ़साइकल ऑब्ज़र्वर, जो लाइफ़साइकल की स्थिति पर नज़र रखते हैं और लाइफ़साइकल में बदलाव होने पर टास्क पूरे करते हैं. लाइफ़साइकल ऑब्ज़र्वर, LifecycleObserver इंटरफ़ेस को लागू करते हैं.

इस टास्क में, आपको DessertClicker ऐप्लिकेशन को Android लाइफ़साइकल लाइब्रेरी का इस्तेमाल करने के लिए बदलना है. साथ ही, यह जानना है कि लाइब्रेरी की मदद से, Android ऐक्टिविटी और फ़्रैगमेंट के लाइफ़साइकल को मैनेज करना कितना आसान हो जाता है.

पहला चरण: DessertTimer को LifecycleObserver में बदलना

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

  1. DesertTimer.kt क्लास खोलें.
  2. DessertTimer क्लास के क्लास सिग्नेचर को इस तरह बदलें:
class DessertTimer(lifecycle: Lifecycle) : LifecycleObserver {

क्लास की इस नई परिभाषा से दो काम होते हैं:

  • कंस्ट्रक्टर, Lifecycle ऑब्जेक्ट लेता है. यह वह लाइफ़साइकल होता है जिसे टाइमर ऑब्ज़र्व कर रहा होता है.
  • क्लास की परिभाषा, LifecycleObserver इंटरफ़ेस को लागू करती है.
  1. runnable वैरिएबल के नीचे, क्लास की परिभाषा में init ब्लॉक जोड़ें. init ब्लॉक में, addObserver() तरीके का इस्तेमाल करके, मालिक (ऐक्टिविटी) से पास किए गए लाइफ़साइकल ऑब्जेक्ट को इस क्लास (ऑब्ज़र्वर) से कनेक्ट करें.
 init {
   lifecycle.addObserver(this)
}
  1. startTimer() को @OnLifecycleEvent annotation के साथ एनोटेट करें और ON_START लाइफ़साइकल इवेंट का इस्तेमाल करें. लाइफ़साइकल के सभी इवेंट, Lifecycle.Event क्लास में होते हैं. इन्हें आपका लाइफ़साइकल ऑब्ज़र्वर देख सकता है.
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun startTimer() {
  1. stopTimer() के लिए भी यही तरीका अपनाएं. इसके लिए, ON_STOP इवेंट का इस्तेमाल करें:
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopTimer()

दूसरा चरण: MainActivity में बदलाव करना

आपकी MainActivity क्लास, इनहेरिटेंस के ज़रिए पहले से ही लाइफ़साइकल का मालिक है. ऐसा इसलिए है, क्योंकि FragmentActivity सुपरक्लास, LifecycleOwner को लागू करता है. इसलिए, आपको अपनी गतिविधि को लाइफ़साइकल के बारे में जानकारी देने के लिए कुछ भी करने की ज़रूरत नहीं है. आपको सिर्फ़ ऐक्टिविटी के लाइफ़साइकल ऑब्जेक्ट को DessertTimer कंस्ट्रक्टर में पास करना है.

  1. MainActivity खोलें. onCreate() तरीके में, DessertTimer को शुरू करने के तरीके में बदलाव करके this.lifecycle को शामिल करें:
dessertTimer = DessertTimer(this.lifecycle)

गतिविधि की lifecycle प्रॉपर्टी में, वह Lifecycle ऑब्जेक्ट होता है जिसका मालिकाना हक इस गतिविधि के पास होता है.

  1. onCreate() में startTimer() को किए गए कॉल और onStop() में stopTimer() को किए गए कॉल को हटाओ. अब आपको DessertTimer को यह बताने की ज़रूरत नहीं है कि गतिविधि में क्या करना है. ऐसा इसलिए, क्योंकि DessertTimer अब लाइफ़साइकल को खुद ही मॉनिटर कर रहा है. साथ ही, लाइफ़साइकल की स्थिति में बदलाव होने पर, इसे अपने-आप सूचना मिल जाती है. अब इन कॉलबैक में सिर्फ़ मैसेज लॉग किया जाता है.
  2. ऐप्लिकेशन को कंपाइल और रन करें. इसके बाद, Logcat खोलें. ध्यान दें कि टाइमर शुरू हो गया है, जैसा कि उम्मीद थी.
  3. ऐप्लिकेशन को बैकग्राउंड में चलाने के लिए, होम बटन पर क्लिक करें. ध्यान दें कि टाइमर उम्मीद के मुताबिक चलना बंद हो गया है.

अगर Android, बैकग्राउंड में चल रहे किसी ऐप्लिकेशन को बंद कर देता है, तो उस ऐप्लिकेशन और उसके डेटा का क्या होता है? इस मुश्किल एज केस को समझना ज़रूरी है.

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

Android, बैकग्राउंड में चल रहे ऐप्लिकेशन को मैनेज करता है, ताकि फ़ोरग्राउंड में चल रहा ऐप्लिकेशन बिना किसी समस्या के काम कर सके. उदाहरण के लिए, Android यह तय करता है कि बैकग्राउंड में चल रहे ऐप्लिकेशन, कितनी प्रोसेसिंग कर सकते हैं.

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

इस टास्क में, Android प्रोसेस के बंद होने की स्थिति को सिम्युलेट किया जाता है. साथ ही, यह देखा जाता है कि जब ऐप्लिकेशन फिर से शुरू होता है, तो क्या होता है.

पहला चरण: adb का इस्तेमाल करके, प्रोसेस बंद होने की स्थिति का सिम्युलेट करना

Android डीबग ब्रिज (adb) एक कमांड-लाइन टूल है. इसकी मदद से, अपने कंप्यूटर से कनेक्ट किए गए डिवाइसों और एम्युलेटर को निर्देश भेजे जा सकते हैं. इस चरण में, आपको adb का इस्तेमाल करके अपने ऐप्लिकेशन की प्रोसेस बंद करनी होगी. साथ ही, यह देखना होगा कि Android आपके ऐप्लिकेशन को बंद करने पर क्या होता है.

  1. अपने ऐप्लिकेशन को कंपाइल करें और चलाएं. कप केक पर कुछ बार क्लिक करें.
  2. अपने ऐप्लिकेशन को बैकग्राउंड में रखने के लिए, होम बटन दबाएं. अब आपका ऐप्लिकेशन बंद हो गया है. अगर Android को उन संसाधनों की ज़रूरत पड़ती है जिनका इस्तेमाल ऐप्लिकेशन कर रहा है, तो ऐप्लिकेशन को बंद किया जा सकता है.
  3. Android Studio में, कमांड-लाइन टर्मिनल खोलने के लिए टर्मिनल टैब पर क्लिक करें.
  4. adb टाइप करें और Return दबाएं.

    अगर आपको ऐसा बहुत सारा आउटपुट दिखता है जो Android Debug Bridge version X.XX.X से शुरू होता है और tags to be used by logcat (see logcat —help) पर खत्म होता है, तो इसका मतलब है कि सब कुछ ठीक है. अगर आपको इसके बजाय adb: command not found दिखता है, तो पक्का करें कि adb: command not found कमांड आपके एक्ज़ीक्यूशन पाथ में उपलब्ध हो.adb निर्देशों के लिए, यूटिलिटी चैप्टर में "adb को अपने एक्ज़ीक्यूशन पाथ में जोड़ें" देखें.
  5. इस टिप्पणी को कॉपी करके कमांड लाइन में चिपकाएं और Return दबाएं:
adb shell am kill com.example.android.dessertclicker

इस कमांड से, कनेक्ट किए गए सभी डिवाइसों या एम्युलेटर को dessertclicker पैकेज नेम वाली प्रोसेस को रोकने के लिए कहा जाता है. हालांकि, ऐसा सिर्फ़ तब किया जाता है, जब ऐप्लिकेशन बैकग्राउंड में चल रहा हो. आपका ऐप्लिकेशन बैकग्राउंड में चल रहा था. इसलिए, डिवाइस या एम्युलेटर की स्क्रीन पर यह नहीं दिखता कि आपकी प्रोसेस बंद कर दी गई है. Android Studio में, Run टैब पर क्लिक करें. आपको "Application terminated" मैसेज दिखेगा. Logcat टैब पर क्लिक करके देखें कि onDestroy() कॉलबैक कभी नहीं चला. आपकी गतिविधि बस खत्म हो गई.

  1. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन वाली स्क्रीन का इस्तेमाल करें. आपका ऐप्लिकेशन, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन वाली स्क्रीन पर दिखता है. भले ही, उसे बैकग्राउंड में रखा गया हो या पूरी तरह से बंद कर दिया गया हो. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन की स्क्रीन का इस्तेमाल करने पर, ऐक्टिविटी फिर से शुरू हो जाती है. गतिविधि, स्टार्टअप लाइफ़साइकल के सभी कॉलबैक से गुज़रती है. इसमें onCreate() भी शामिल है.
  2. ध्यान दें कि ऐप्लिकेशन को फिर से चालू करने पर, "स्कोर" (बेचे गए डेज़र्ट की संख्या और कुल डॉलर, दोनों) डिफ़ॉल्ट वैल्यू (0) पर रीसेट हो जाता है. अगर Android ने आपके ऐप्लिकेशन को बंद कर दिया, तो उसकी स्थिति को सेव क्यों नहीं किया गया?

    जब ओएस आपके ऐप्लिकेशन को रीस्टार्ट करता है, तो Android आपके ऐप्लिकेशन को पहले वाली स्थिति पर रीसेट करने की पूरी कोशिश करता है. जब भी गतिविधि से बाहर जाया जाता है, तब Android आपके कुछ व्यू की स्थिति को बंडल में सेव कर लेता है. अपने-आप सेव होने वाले डेटा के कुछ उदाहरण यहां दिए गए हैं: EditText में मौजूद टेक्स्ट (जब तक लेआउट में उनका आईडी सेट है) और आपकी गतिविधि का बैक स्टैक.

    हालांकि, कभी-कभी Android OS को आपके सभी डेटा के बारे में पता नहीं होता. उदाहरण के लिए, अगर आपके पास DessertClicker ऐप्लिकेशन में revenue जैसा कोई कस्टम वैरिएबल है, तो Android OS को इस डेटा या आपकी गतिविधि के लिए इसके महत्व के बारे में पता नहीं होता. आपको इस डेटा को बंडल में खुद जोड़ना होगा.

दूसरा चरण: बंडल डेटा सेव करने के लिए, onSaveInstanceState() का इस्तेमाल करना

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

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

  1. MainActivity में, onSaveInstanceState() कॉलबैक को बदलें और Timber लॉग स्टेटमेंट जोड़ें.
override fun onSaveInstanceState(outState: Bundle) {
   super.onSaveInstanceState(outState)

   Timber.i("onSaveInstanceState Called")
}
  1. ऐप्लिकेशन को कंपाइल और रन करें. इसके बाद, उसे बैकग्राउंड में रखने के लिए होम बटन पर क्लिक करें. ध्यान दें कि onSaveInstanceState() कॉलबैक, onPause() और onStop() के ठीक बाद ट्रिगर होता है:
  2. फ़ाइल में सबसे ऊपर, क्लास की परिभाषा से ठीक पहले, इन कॉन्स्टेंट को जोड़ें:
const val KEY_REVENUE = "revenue_key"
const val KEY_DESSERT_SOLD = "dessert_sold_key"
const val KEY_TIMER_SECONDS = "timer_seconds_key"

इन कुंजियों का इस्तेमाल, इंस्टेंस की स्थिति वाले बंडल से डेटा सेव करने और वापस पाने, दोनों के लिए किया जाएगा.

  1. नीचे की ओर स्क्रोल करके onSaveInstanceState() पर जाएं. इसके बाद, outState पैरामीटर देखें. यह Bundle टाइप का होता है.

    बंडल, की-वैल्यू पेयर का कलेक्शन होता है. इसमें कुंजियां हमेशा स्ट्रिंग होती हैं. बंडल में, प्रिमिटिव वैल्यू डाली जा सकती हैं. जैसे, int और boolean वैल्यू.
    सिस्टम इस बंडल को रैम में रखता है. इसलिए, बंडल में कम डेटा रखना सबसे सही तरीका है. इस बंडल का साइज़ भी सीमित होता है. हालांकि, यह साइज़ अलग-अलग डिवाइसों के हिसाब से अलग-अलग होता है. आम तौर पर, आपको 100 के से कम आइटम सेव करने चाहिए. ऐसा न करने पर, TransactionTooLargeException गड़बड़ी की वजह से आपका ऐप्लिकेशन क्रैश हो सकता है.
  2. onSaveInstanceState() में, revenue वैल्यू (पूर्णांक) को putInt() तरीके से बंडल में डालें:
outState.putInt(KEY_REVENUE, revenue)

putInt() तरीके (और Bundle क्लास के मिलते-जुलते तरीके, जैसे कि putFloat() और putString()) में दो आर्ग्युमेंट होते हैं: की के लिए एक स्ट्रिंग (KEY_REVENUE कॉन्स्टेंट) और सेव की जाने वाली असल वैल्यू.

  1. बेचे गए डेज़र्ट की संख्या और टाइमर के स्टेटस के लिए, इसी प्रोसेस को दोहराएं:
outState.putInt(KEY_DESSERT_SOLD, dessertsSold)
outState.putInt(KEY_TIMER_SECONDS, dessertTimer.secondsCount)

तीसरा चरण: बंडल डेटा को वापस लाने के लिए onCreate() का इस्तेमाल करना

  1. ऊपर की ओर स्क्रोल करके onCreate() पर जाएं और तरीके के सिग्नेचर की जांच करें:
override fun onCreate(savedInstanceState: Bundle) {

ध्यान दें कि onCreate() को हर बार कॉल करने पर Bundle मिलता है. जब प्रोसेस बंद होने की वजह से आपकी गतिविधि फिर से शुरू होती है, तो सेव किया गया बंडल onCreate() को पास कर दिया जाता है. अगर आपकी गतिविधि नई है, तो onCreate() में यह बंडल null है. इसलिए, अगर बंडल null नहीं है, तो आपको पता चल जाएगा कि आपने पहले से मौजूद किसी पॉइंट से गतिविधि को "फिर से बनाया" है.

  1. DessertTimer सेटअप करने के बाद, onCreate() में यह कोड जोड़ें:
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
}

null के लिए किए गए टेस्ट से यह पता चलता है कि बंडल में डेटा है या बंडल null है. इससे यह पता चलता है कि ऐप्लिकेशन को नए सिरे से शुरू किया गया है या बंद होने के बाद फिर से बनाया गया है. यह टेस्ट, बंडल से डेटा वापस लाने का एक सामान्य पैटर्न है.

ध्यान दें कि आपने यहां जिस कुंजी (KEY_REVENUE) का इस्तेमाल किया है वही कुंजी आपने putInt() के लिए भी इस्तेमाल की है. हर बार एक ही कुंजी का इस्तेमाल करने के लिए, उन कुंजियों को कॉन्स्टेंट के तौर पर तय करना सबसे सही तरीका है. बंडल से डेटा निकालने के लिए, getInt() का इस्तेमाल किया जाता है. ठीक उसी तरह जैसे बंडल में डेटा डालने के लिए, putInt() का इस्तेमाल किया जाता है. getInt() तरीके में दो आर्ग्युमेंट होते हैं:

  • यह एक स्ट्रिंग होती है, जो कुंजी के तौर पर काम करती है. उदाहरण के लिए, रेवेन्यू वैल्यू के लिए "key_revenue".
  • अगर बंडल में उस कुंजी के लिए कोई वैल्यू मौजूद नहीं है, तो डिफ़ॉल्ट वैल्यू.

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

  1. बेचे गए डेज़र्ट की संख्या और टाइमर की वैल्यू को वापस लाने के लिए, getInt() तरीके जोड़ें:
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount =
       savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
}
  1. ऐप्लिकेशन को कंपाइल और रन करें. कप केक को कम से कम पांच बार तब तक दबाएं, जब तक वह डोनट में न बदल जाए. ऐप्लिकेशन को बैकग्राउंड में रखने के लिए, होम पर क्लिक करें.
  2. ऐप्लिकेशन की प्रोसेस बंद करने के लिए, Android Studio के टर्मिनल टैब में जाकर adb चलाएं.
adb shell am kill com.example.android.dessertclicker
  1. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन वाली स्क्रीन का इस्तेमाल करें. ध्यान दें कि इस बार ऐप्लिकेशन, बंडल से मिले सही रेवेन्यू और बेचे गए डेज़र्ट की वैल्यू के साथ वापस आता है. हालांकि, यह भी ध्यान दें कि डेज़र्ट को वापस कपकेक में बदल दिया गया है. ऐप्लिकेशन को बंद करने से पहले की स्थिति में वापस लाने के लिए, एक और काम करना बाकी है.
  2. MainActivity में, showCurrentDessert() तरीके की जांच करें. ध्यान दें कि यह तरीका तय करता है कि गतिविधि में कौनसी डेज़र्ट इमेज दिखनी चाहिए. यह इस बात पर निर्भर करता है कि अब तक कितने डेज़र्ट बेचे गए हैं और allDesserts वैरिएबल में डेज़र्ट की सूची क्या है.
for (dessert in allDesserts) {
   if (dessertsSold >= dessert.startProductionAmount) {
       newDessert = dessert
   }
    else break
}

इस तरीके में, सही इमेज चुनने के लिए बेचे गए डेज़र्ट की संख्या का इस्तेमाल किया जाता है. इसलिए, आपको onSaveInstanceState() में बंडल की इमेज का रेफ़रंस सेव करने के लिए कुछ भी करने की ज़रूरत नहीं है. उस बंडल में, बेचे गए डेज़र्ट की संख्या पहले से ही सेव की जा रही है.

  1. onCreate() में, बंडल से स्थिति को वापस लाने वाले ब्लॉक में, showCurrentDessert() को कॉल करें:
 if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
   dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount = 
      savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
   showCurrentDessert()                   
}
  1. ऐप्लिकेशन को कंपाइल और चलाएं. इसके बाद, इसे बैकग्राउंड में रखें. प्रोसेस बंद करने के लिए, adb का इस्तेमाल करें. ऐप्लिकेशन पर वापस जाने के लिए, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन की स्क्रीन का इस्तेमाल करें. ध्यान दें कि अब डेज़र्ट की बताई गई दोनों वैल्यू, कुल रेवेन्यू, और डेज़र्ट की इमेज सही तरीके से वापस आ गई हैं.

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

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

पहला चरण: डिवाइस को घुमाने की सुविधा और लाइफ़साइकल कॉलबैक के बारे में जानें

  1. अपने ऐप्लिकेशन को कंपाइल और रन करें. इसके बाद, Logcat खोलें.
  2. डिवाइस या एम्युलेटर को लैंडस्केप मोड में घुमाएं. एम्युलेटर को घुमाने के लिए, रोटेशन बटन का इस्तेमाल करें. इसके अलावा, Control और ऐरो बटन (Mac पर Command और ऐरो बटन) का इस्तेमाल करके भी एम्युलेटर को घुमाया जा सकता है.
  3. Logcat में आउटपुट की जांच करें. MainActivity के हिसाब से आउटपुट को फ़िल्टर करें.
    ध्यान दें कि जब डिवाइस या एम्युलेटर स्क्रीन को घुमाता है, तो सिस्टम ऐक्टिविटी को बंद करने के लिए, लाइफ़साइकल के सभी कॉलबैक को कॉल करता है. इसके बाद, ऐक्टिविटी को फिर से बनाया जाता है. साथ ही, सिस्टम ऐक्टिविटी को शुरू करने के लिए, लाइफ़साइकल के सभी कॉलबैक को कॉल करता है.
  4. MainActivity में, पूरे onSaveInstanceState() तरीके को टिप्पणी के तौर पर मार्क करें.
  5. अपने ऐप्लिकेशन को फिर से कंपाइल और रन करें. कपकेक पर कुछ बार क्लिक करें और डिवाइस या एम्युलेटर को घुमाएं. इस बार, डिवाइस को घुमाने पर गतिविधि बंद हो जाती है और फिर से शुरू होती है. ऐसा होने पर, गतिविधि डिफ़ॉल्ट वैल्यू के साथ शुरू होती है.

    कॉन्फ़िगरेशन में बदलाव होने पर, Android उसी इंस्टेंस स्टेट बंडल का इस्तेमाल करता है जिसके बारे में आपने पिछले टास्क में सीखा था. इसका इस्तेमाल, ऐप्लिकेशन की स्थिति को सेव और वापस लाने के लिए किया जाता है. प्रोसेस बंद होने पर, onSaveInstanceState() का इस्तेमाल करके अपने ऐप्लिकेशन के डेटा को बंडल में डालें. इसके बाद, onCreate() में डेटा वापस लाएं, ताकि डिवाइस को घुमाने पर गतिविधि की स्थिति का डेटा न मिटे.
  6. MainActivity में, onSaveInstanceState() तरीके से अनकमेंट करें, ऐप्लिकेशन चलाएं, कपकेक पर क्लिक करें, और ऐप्लिकेशन या डिवाइस को घुमाएं. ध्यान दें कि इस बार गतिविधि रोटेशन के दौरान, डेज़र्ट का डेटा सेव रहता है.

Android Studio प्रोजेक्ट: DessertClickerFinal

लाइफ़साइकल से जुड़ी सलाह

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

लाइफ़साइकल लाइब्रेरी

  • Android लाइफ़साइकल लाइब्रेरी का इस्तेमाल करके, लाइफ़साइकल कंट्रोल को ऐक्टिविटी या फ़्रैगमेंट से उस कॉम्पोनेंट पर ट्रांसफ़र करें जिसे लाइफ़साइकल की जानकारी की ज़रूरत है.
  • लाइफ़साइकल के मालिक ऐसे कॉम्पोनेंट होते हैं जिनकी लाइफ़साइकल होती है. इनमें Activity और Fragment शामिल हैं. लाइफ़साइकल के मालिक, LifecycleOwner इंटरफ़ेस को लागू करते हैं.
  • लाइफ़साइकल ऑब्ज़र्वर, लाइफ़साइकल की मौजूदा स्थिति पर ध्यान देते हैं. साथ ही, लाइफ़साइकल में बदलाव होने पर टास्क पूरे करते हैं. लाइफ़साइकल ऑब्ज़र्वर, LifecycleObserver इंटरफ़ेस को लागू करते हैं.
  • Lifecycle ऑब्जेक्ट में लाइफ़साइकल की मौजूदा स्थितियां होती हैं. साथ ही, लाइफ़साइकल में बदलाव होने पर ये इवेंट ट्रिगर करते हैं.

लाइफ़साइकल के बारे में जानकारी रखने वाली क्लास बनाने के लिए:

  • लाइफ़साइकल की जानकारी रखने वाली क्लास में, LifecycleObserver इंटरफ़ेस लागू करें.
  • ऐक्टिविटी या फ़्रैगमेंट से लाइफ़साइकल ऑब्जेक्ट के साथ, लाइफ़साइकल ऑब्ज़र्वर क्लास को शुरू करें.
  • लाइफ़साइकल ऑब्ज़र्वर क्लास में, लाइफ़साइकल के बारे में जानकारी रखने वाले तरीकों को उस लाइफ़साइकल की स्थिति में बदलाव के साथ एनोटेट करें जिसमें उनकी दिलचस्पी है.

    उदाहरण के लिए, @OnLifecycleEvent(Lifecycle.Event.ON_START)एनोटेशन से पता चलता है कि यह तरीका onStart लाइफ़साइकल इवेंट पर नज़र रख रहा है.

प्रोसेस बंद होने और गतिविधि की स्थिति सेव होने के बारे में जानकारी

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

गतिविधि और फ़्रैगमेंट की स्थिति को बनाए रखना

  • जब आपका ऐप्लिकेशन बैकग्राउंड में चला जाता है, तब onStop() को कॉल करने के तुरंत बाद, ऐप्लिकेशन का डेटा बंडल में सेव हो जाता है. ऐप्लिकेशन का कुछ डेटा, जैसे कि EditText का कॉन्टेंट, आपके लिए अपने-आप सेव हो जाता है.
  • बंडल, Bundle का एक इंस्टेंस होता है. यह कुंजियों और वैल्यू का कलेक्शन होता है. कुंजियां हमेशा स्ट्रिंग होती हैं.
  • onSaveInstanceState() कॉलबैक का इस्तेमाल करके, बंडल में वह डेटा सेव करें जिसे आपको बनाए रखना है. भले ही, ऐप्लिकेशन अपने-आप बंद हो गया हो. बंडल में डेटा डालने के लिए, put से शुरू होने वाले बंडल के तरीकों का इस्तेमाल करें. जैसे, putInt().
  • डेटा को बंडल से बाहर निकालने के लिए, onRestoreInstanceState() या onCreate() तरीके का इस्तेमाल किया जा सकता है. onCreate() तरीके में savedInstanceState पैरामीटर होता है, जिसमें बंडल होता है.
  • अगर savedInstanceState वैरिएबल में null शामिल है, तो इसका मतलब है कि गतिविधि को स्टेट बंडल के बिना शुरू किया गया था और वापस पाने के लिए कोई स्टेट डेटा नहीं है.
  • किसी कुंजी की मदद से बंडल से डेटा वापस पाने के लिए, Bundle से शुरू होने वाले get तरीकों का इस्तेमाल करें. जैसे, getInt().

कॉन्फ़िगरेशन में बदलाव

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

Udacity का कोर्स:

Android डेवलपर का दस्तावेज़:

अन्य:

इस सेक्शन में, उन छात्र-छात्राओं के लिए होमवर्क असाइनमेंट की सूची दी गई है जो किसी शिक्षक के कोर्स के हिस्से के तौर पर इस कोडलैब पर काम कर रहे हैं. शिक्षक के पास ये विकल्प होते हैं:

  • अगर ज़रूरी हो, तो होमवर्क असाइन करें.
  • छात्र-छात्राओं को बताएं कि होमवर्क असाइनमेंट कैसे सबमिट किए जाते हैं.
  • होमवर्क असाइनमेंट को ग्रेड दें.

शिक्षक इन सुझावों का इस्तेमाल अपनी ज़रूरत के हिसाब से कर सकते हैं. साथ ही, वे चाहें, तो कोई दूसरा होमवर्क भी दे सकते हैं.

अगर आपको यह कोडलैब खुद से पूरा करना है, तो अपनी जानकारी की जांच करने के लिए, इन होमवर्क असाइनमेंट का इस्तेमाल करें.

ऐप्लिकेशन बदलना

पहले लेसन में बनाया गया DiceRoller ऐप्लिकेशन खोलें. (अगर आपके पास यह ऐप्लिकेशन नहीं है, तो इसे यहां से डाउनलोड करें.) ऐप्लिकेशन को कंपाइल और रन करें. ध्यान दें कि डिवाइस को घुमाने पर, डाइस की मौजूदा वैल्यू मिट जाती है. बंडल में उस वैल्यू को बनाए रखने के लिए, onSaveInstanceState() को लागू करें. साथ ही, onCreate() में उस वैल्यू को वापस लाएं.

इन सवालों के जवाब दें

पहला सवाल

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

  • फ़ोन कॉल के दौरान, आपको फ़िज़िक्स सिमुलेशन में ऑब्जेक्ट की पोज़िशन का हिसाब लगाते रहना चाहिए.
  • फ़ोन कॉल के दौरान, आपको फ़िज़िक्स सिमुलेशन में ऑब्जेक्ट की पोज़िशन का हिसाब लगाना बंद कर देना चाहिए.

दूसरा सवाल

जब ऐप्लिकेशन स्क्रीन पर न हो, तब सिम्युलेशन को रोकने के लिए, आपको लाइफ़साइकल के किस तरीके को बदलना चाहिए?

  • onDestroy()
  • onStop()
  • onPause()
  • onSaveInstanceState()

तीसरा सवाल

Android लाइफ़साइकल लाइब्रेरी की मदद से, किसी क्लास को लाइफ़साइकल के बारे में जानकारी देने के लिए, क्लास को कौनसा इंटरफ़ेस लागू करना चाहिए?

  • Lifecycle
  • LifecycleOwner
  • Lifecycle.Event
  • LifecycleObserver

Question 4

आपकी गतिविधि में onCreate() तरीके को किन स्थितियों में Bundle मिलता है, जिसमें डेटा मौजूद होता है (यानी कि Bundle, null नहीं होता)? एक से ज़्यादा जवाब लागू हो सकते हैं.

  • डिवाइस को घुमाने के बाद, गतिविधि फिर से शुरू हो जाती है.
  • गतिविधि को नए सिरे से शुरू किया जाता है.
  • बैकग्राउंड से वापस आने के बाद, गतिविधि फिर से शुरू हो जाती है.
  • डिवाइस को रीबूट किया जाता है.

अगला सबक शुरू करें: 5.1: ViewModel और ViewModelFactory

इस कोर्स में मौजूद अन्य कोडलैब के लिंक के लिए, Android Kotlin Fundamentals कोडलैब का लैंडिंग पेज देखें.