Android Kotlin Fundamentals 05.3: ViewModel और LiveData के साथ डेटा बाइंडिंग

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

परिचय

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

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

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

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

  • Kotlin में बुनियादी Android ऐप्लिकेशन बनाने का तरीका.
  • ऐक्टिविटी और फ़्रैगमेंट की लाइफ़साइकल कैसे काम करती हैं.
  • अपने ऐप्लिकेशन में ViewModel ऑब्जेक्ट इस्तेमाल करने का तरीका.
  • ViewModel में LiveData का इस्तेमाल करके डेटा सेव करने का तरीका.
  • LiveData डेटा में हुए बदलावों को देखने के लिए, ऑब्ज़र्वर के तरीके कैसे जोड़ें.

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

  • डेटा बाइंडिंग लाइब्रेरी के एलिमेंट इस्तेमाल करने का तरीका.
  • डेटा बाइंडिंग के साथ ViewModel को इंटिग्रेट करने का तरीका.
  • डेटा बाइंडिंग के साथ LiveData को इंटिग्रेट करने का तरीका.
  • किसी फ़्रैगमेंट में क्लिक लिसनर बदलने के लिए, लिसनर बाइंडिंग का इस्तेमाल कैसे करें.
  • डेटा-बाइंडिंग एक्सप्रेशन में स्ट्रिंग फ़ॉर्मैटिंग जोड़ने का तरीका.

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

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

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

पहला खिलाड़ी, ऐप्लिकेशन में दिए गए शब्दों को देखता है और एक-एक करके उन पर ऐक्ट करता है. वह यह पक्का करता है कि दूसरा खिलाड़ी उन शब्दों को न देख पाए. दूसरा खिलाड़ी, शब्द का अनुमान लगाने की कोशिश करता है.

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

पहला खिलाड़ी, शब्द को बोलकर नहीं, बल्कि ऐक्टिंग करके बताता है.

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

इस कोडलैब में, LiveData ऑब्जेक्ट में LiveData के साथ डेटा बाइंडिंग को इंटिग्रेट करके, GuessTheWord ऐप्लिकेशन को बेहतर बनाया जाता है.ViewModel इससे लेआउट में मौजूद व्यू और ViewModel ऑब्जेक्ट के बीच कम्यूनिकेशन अपने-आप हो जाता है. साथ ही, LiveData का इस्तेमाल करके, अपने कोड को आसान बनाया जा सकता है.

शीर्षक स्क्रीन

गेम की स्क्रीन

स्कोर स्क्रीन

इस टास्क में, आपको इस कोडलैब के लिए स्टार्टर कोड ढूंढना और उसे चलाना है. पिछले कोडलैब में बनाए गए GuessTheWord ऐप्लिकेशन को स्टार्टर कोड के तौर पर इस्तेमाल किया जा सकता है. इसके अलावा, स्टार्टर ऐप्लिकेशन भी डाउनलोड किया जा सकता है.

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

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

ऐप्लिकेशन का मौजूदा आर्किटेक्चर

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

उदाहरण के लिए:

  • ठीक है बटन को game_fragment.xml लेआउट फ़ाइल में Button व्यू के तौर पर तय किया गया है.
  • जब उपयोगकर्ता ठीक है बटन पर टैप करता है, तब GameFragment फ़्रैगमेंट में मौजूद क्लिक लिसनर, GameViewModel में मौजूद क्लिक लिसनर को कॉल करता है.
  • स्कोर को GameViewModel में अपडेट किया जाता है.

Button व्यू और GameViewModel सीधे तौर पर कम्यूनिकेट नहीं करते. इसके लिए, उन्हें GameFragment में मौजूद क्लिक लिसनर की ज़रूरत होती है.

डेटा बाइंडिंग में पास किया गया ViewModel

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

ViewModel ऑब्जेक्ट, GuessTheWord ऐप्लिकेशन में यूज़र इंटरफ़ेस (यूआई) का पूरा डेटा सेव रखते हैं. डेटा बाइंडिंग में ViewModel ऑब्जेक्ट पास करके, व्यू और ViewModel ऑब्जेक्ट के बीच कुछ कम्यूनिकेशन ऑटोमेट किया जा सकता है.

इस टास्क में, GameViewModel और ScoreViewModel क्लास को उनके एक्सएमएल लेआउट से जोड़ा जाता है. आपने क्लिक इवेंट को मैनेज करने के लिए, लिसनर बाइंडिंग भी सेट अप की हैं.

पहला चरण: GameViewModel के लिए डेटा बाइंडिंग जोड़ना

इस चरण में, GameViewModel को उससे जुड़ी लेआउट फ़ाइल, game_fragment.xml से जोड़ा जाता है.

  1. game_fragment.xml फ़ाइल में, GameViewModel टाइप का डेटा-बाइंडिंग वैरिएबल जोड़ें. अगर आपको Android Studio में गड़बड़ियां दिख रही हैं, तो प्रोजेक्ट को क्लीन और रीबिल्ड करें.
<layout ...>

   <data>

       <variable
           name="gameViewModel"
           type="com.example.android.guesstheword.screens.game.GameViewModel" />
   </data>
  
   <androidx.constraintlayout...
  1. GameFragment फ़ाइल में, GameViewModel को डेटा बाइंडिंग में पास करें.

    इसके लिए, viewModel को binding.gameViewModel वैरिएबल असाइन करें. यह वैरिएबल आपने पिछले चरण में घोषित किया था. इस कोड को viewModel के शुरू होने के बाद, onCreateView() में डालें. अगर आपको Android Studio में गड़बड़ियां दिख रही हैं, तो प्रोजेक्ट को क्लीन और रीबिल्ड करें.
// Set the viewmodel for databinding - this allows the bound layout access 
// to all the data in the ViewModel
binding.gameViewModel = viewModel

दूसरा चरण: इवेंट हैंडलिंग के लिए लिसनर बाइंडिंग का इस्तेमाल करना

लिसनर बाइंडिंग, बाइंडिंग एक्सप्रेशन होते हैं. ये onClick(), onZoomIn() या onZoomOut() जैसे इवेंट ट्रिगर होने पर काम करते हैं. लिसनर बाइंडिंग को लैम्डा एक्सप्रेशन के तौर पर लिखा जाता है.

डेटा बाइंडिंग, एक लिसनर बनाती है और उसे व्यू पर सेट करती है. जब लिसन किया गया इवेंट होता है, तो लिसनर, लैम्डा एक्सप्रेशन का आकलन करता है. लिसनर बाइंडिंग, Android Gradle प्लगिन 2.0 या इसके बाद के वर्शन के साथ काम करती हैं. ज़्यादा जानने के लिए, लेआउट और बाइंडिंग एक्सप्रेशन पढ़ें.

इस चरण में, GameFragment में मौजूद क्लिक लिसनर को game_fragment.xml फ़ाइल में मौजूद लिसनर बाइंडिंग से बदला जाता है.

  1. game_fragment.xml में, skip_button में onClick एट्रिब्यूट जोड़ें. बाइंडिंग एक्सप्रेशन तय करें और GameViewModel में onSkip() वाले तरीके को कॉल करें. इस बाइंडिंग एक्सप्रेशन को लिसनर बाइंडिंग कहा जाता है.
<Button
   android:id="@+id/skip_button"
   ...
   android:onClick="@{() -> gameViewModel.onSkip()}"
   ... />
  1. इसी तरह, correct_button के क्लिक इवेंट को GameViewModel में मौजूद onCorrect() तरीके से बाइंड करें.
<Button
   android:id="@+id/correct_button"
   ...
   android:onClick="@{() -> gameViewModel.onCorrect()}"
   ... />
  1. end_game_button के क्लिक इवेंट को GameViewModel में मौजूद onGameFinish() तरीके से बाइंड करें.
<Button
   android:id="@+id/end_game_button"
   ...
   android:onClick="@{() -> gameViewModel.onGameFinish()}"
   ... />
  1. GameFragment में, क्लिक लिसनर सेट करने वाले स्टेटमेंट हटाएं. साथ ही, क्लिक लिसनर कॉल करने वाले फ़ंक्शन हटाएं. अब आपको उनकी ज़रूरत नहीं है.

हटाने के लिए कोड:

binding.correctButton.setOnClickListener { onCorrect() }
binding.skipButton.setOnClickListener { onSkip() }
binding.endGameButton.setOnClickListener { onEndGame() }

/** Methods for buttons presses **/
private fun onSkip() {
   viewModel.onSkip()
}
private fun onCorrect() {
   viewModel.onCorrect()
}
private fun onEndGame() {
   gameFinished()
}

तीसरा चरण: ScoreViewModel के लिए डेटा बाइंडिंग जोड़ना

इस चरण में, ScoreViewModel को उससे जुड़ी लेआउट फ़ाइल, score_fragment.xml से जोड़ा जाता है.

  1. score_fragment.xml फ़ाइल में, ScoreViewModel टाइप का बाइंडिंग वैरिएबल जोड़ें. यह चरण, ऊपर दिए गए GameViewModel चरण की तरह ही है.
<layout ...>
   <data>
       <variable
           name="scoreViewModel"
           type="com.example.android.guesstheword.screens.score.ScoreViewModel" />
   </data>
   <androidx.constraintlayout.widget.ConstraintLayout
  1. score_fragment.xml में, play_again_button में onClick एट्रिब्यूट जोड़ें. लिसनर बाइंडिंग तय करें और ScoreViewModel में onPlayAgain() तरीके को कॉल करें.
<Button
   android:id="@+id/play_again_button"
   ...
   android:onClick="@{() -> scoreViewModel.onPlayAgain()}"
   ... />
  1. ScoreFragment में, onCreateView() के अंदर, viewModel को शुरू करें. इसके बाद, binding.scoreViewModel बाइंडिंग वैरिएबल को शुरू करें.
viewModel = ...
binding.scoreViewModel = viewModel
  1. ScoreFragment में, playAgainButton के लिए क्लिक लिसनर सेट करने वाला कोड हटाएं. अगर Android Studio में कोई गड़बड़ी दिखती है, तो प्रोजेक्ट को क्लीन और रीबिल्ड करें.

हटाने के लिए कोड:

binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. अपना ऐप्लिकेशन चलाएं. ऐप्लिकेशन पहले की तरह काम करेगा. हालांकि, अब बटन व्यू सीधे तौर पर ViewModel ऑब्जेक्ट के साथ कम्यूनिकेट करते हैं. अब व्यू, ScoreFragment में बटन क्लिक हैंडलर के ज़रिए कम्यूनिकेट नहीं करते हैं.

डेटा-बाइंडिंग से जुड़ी गड़बड़ी के मैसेज की समस्या हल करना

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

अगर आपको गड़बड़ी का ऐसा मैसेज मिलता है जिसे समझना मुश्किल है, तो:

  1. Android Studio के Build पैन में मौजूद मैसेज को ध्यान से देखें. अगर आपको कोई ऐसी जगह दिखती है जिसके आखिर में databinding लिखा है, तो इसका मतलब है कि डेटा बाइंडिंग में कोई गड़बड़ी हुई है.
  2. लेआउट एक्सएमएल फ़ाइल में, डेटा बाइंडिंग का इस्तेमाल करने वाले onClick एट्रिब्यूट में गड़बड़ियां देखें. उस फ़ंक्शन को ढूंढें जिसे लैम्डा एक्सप्रेशन कॉल करता है. साथ ही, पक्का करें कि वह फ़ंक्शन मौजूद हो.
  3. एक्सएमएल के <data> सेक्शन में, डेटा-बाइंडिंग वैरिएबल की स्पेलिंग देखें.

उदाहरण के लिए, एट्रिब्यूट की इस वैल्यू में फ़ंक्शन के नाम onCorrect() की स्पेलिंग गलत है:

android:onClick="@{() -> gameViewModel.onCorrectx()}"

एक्सएमएल फ़ाइल के <data> सेक्शन में, gameViewModel की स्पेलिंग गलत है:

<data>
   <variable
       name="gameViewModelx"
       type="com.example.android.guesstheword.screens.game.GameViewModel" />
</data>

Android Studio, ऐप्लिकेशन को कंपाइल करने से पहले इस तरह की गड़बड़ियों का पता नहीं लगाता. इसके बाद, कंपाइलर गड़बड़ी का यह मैसेज दिखाता है:

error: cannot find symbol
import com.example.android.guesstheword.databinding.GameFragmentBindingImpl"

symbol:   class GameFragmentBindingImpl
location: package com.example.android.guesstheword.databinding

डेटा बाइंडिंग, ViewModel ऑब्जेक्ट के साथ इस्तेमाल किए जाने वाले LiveData के साथ अच्छी तरह से काम करती है. ViewModel ऑब्जेक्ट में डेटा बाइंडिंग जोड़ने के बाद, अब LiveData को शामिल किया जा सकता है.

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

पहला चरण: game_fragment.xml फ़ाइल में LiveData शब्द जोड़ना

इस चरण में, मौजूदा शब्द के टेक्स्ट व्यू को सीधे तौर पर LiveData में मौजूद ViewModel ऑब्जेक्ट से बाइंड किया जाता है.

  1. game_fragment.xml में, word_text टेक्स्ट व्यू में android:text एट्रिब्यूट जोड़ें.

इसे LiveData ऑब्जेक्ट पर सेट करें. इसके लिए, GameViewModel से word का इस्तेमाल करें. साथ ही, बाइंडिंग वैरिएबल gameViewModel का इस्तेमाल करें.

<TextView
   android:id="@+id/word_text"
   ...
   android:text="@{gameViewModel.word}"
   ... />

ध्यान दें कि आपको word.value का इस्तेमाल करने की ज़रूरत नहीं है. इसके बजाय, असल LiveData ऑब्जेक्ट का इस्तेमाल किया जा सकता है. LiveData ऑब्जेक्ट, word की मौजूदा वैल्यू दिखाता है. अगर word की वैल्यू शून्य है, तो LiveData ऑब्जेक्ट एक खाली स्ट्रिंग दिखाता है.

  1. GameFragment में, onCreateView() में, gameViewModel को शुरू करने के बाद, मौजूदा ऐक्टिविटी को binding वैरिएबल के लाइफ़साइकल के मालिक के तौर पर सेट करें. इससे ऊपर दिए गए LiveData ऑब्जेक्ट का स्कोप तय होता है. इससे ऑब्जेक्ट, लेआउट game_fragment.xml में व्यू अपने-आप अपडेट कर पाता है.
binding.gameViewModel = ...
// Specify the current activity as the lifecycle owner of the binding.
// This is used so that the binding can observe LiveData updates
binding.lifecycleOwner = this
  1. GameFragment में, LiveData word के लिए ऑब्ज़र्वर को हटाएं.

हटाने के लिए कोड:

/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})
  1. अपना ऐप्लिकेशन चलाएं और गेम खेलें. अब मौजूदा शब्द को UI कंट्रोलर में ऑब्ज़र्वर तरीके के बिना अपडेट किया जा रहा है.

दूसरा चरण: score_fragment.xml फ़ाइल में score LiveData जोड़ना

इस चरण में, LiveData score को स्कोर फ़्रैगमेंट में मौजूद स्कोर टेक्स्ट व्यू से बाइंड किया जाता है.

  1. score_fragment.xml में, स्कोर टेक्स्ट व्यू में android:text एट्रिब्यूट जोड़ें. text एट्रिब्यूट के लिए scoreViewModel.score असाइन करें. score एक पूर्णांक है. इसलिए, इसे String.valueOf() का इस्तेमाल करके स्ट्रिंग में बदलें.
<TextView
   android:id="@+id/score_text"
   ...
   android:text="@{String.valueOf(scoreViewModel.score)}"
   ... />
  1. ScoreFragment में, scoreViewModel को शुरू करने के बाद, मौजूदा ऐक्टिविटी को binding वैरिएबल के लाइफ़साइकल के मालिक के तौर पर सेट करें.
binding.scoreViewModel = ...
// Specify the current activity as the lifecycle owner of the binding.
// This is used so that the binding can observe LiveData updates
binding.lifecycleOwner = this
  1. ScoreFragment में, score ऑब्जेक्ट के लिए ऑब्ज़र्वर हटाएं.

हटाने के लिए कोड:

// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. अपना ऐप्लिकेशन चलाएं और गेम खेलें. ध्यान दें कि स्कोर फ़्रैगमेंट में स्कोर सही तरीके से दिखाया गया है. साथ ही, स्कोर फ़्रैगमेंट में कोई ऑब्ज़र्वर मौजूद नहीं है.

तीसरा चरण: डेटा बाइंडिंग के साथ स्ट्रिंग फ़ॉर्मैटिंग जोड़ना

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

  1. string.xml में, ये स्ट्रिंग जोड़ें. इनका इस्तेमाल word और score टेक्स्ट व्यू को फ़ॉर्मैट करने के लिए किया जाएगा. %s और %d, मौजूदा शब्द और मौजूदा स्कोर के लिए प्लेसहोल्डर हैं.
<string name="quote_format">\"%s\"</string>
<string name="score_format">Current Score: %d</string>
  1. game_fragment.xml में, quote_format स्ट्रिंग रिसॉर्स का इस्तेमाल करने के लिए, word_text टेक्स्ट व्यू के text एट्रिब्यूट को अपडेट करें. gameViewModel.word से आगे बढ़ें. इससे मौजूदा शब्द को फ़ॉर्मैटिंग स्ट्रिंग के लिए आर्ग्युमेंट के तौर पर पास किया जाता है.
<TextView
   android:id="@+id/word_text"
   ...
   android:text="@{@string/quote_format(gameViewModel.word)}"
   ... />
  1. score टेक्स्ट व्यू को word_text की तरह फ़ॉर्मैट करें. game_fragment.xml में, score_text टेक्स्ट व्यू में text एट्रिब्यूट जोड़ें. स्ट्रिंग रिसोर्स score_format का इस्तेमाल करें. यह एक संख्यात्मक तर्क लेता है, जिसे %d प्लेसहोल्डर के तौर पर दिखाया जाता है. LiveData ऑब्जेक्ट score को इस फ़ॉर्मैटिंग स्ट्रिंग के आर्ग्युमेंट के तौर पर पास करें.
<TextView
   android:id="@+id/score_text"
   ...
   android:text="@{@string/score_format(gameViewModel.score)}"
   ... />
  1. GameFragment क्लास में, onCreateView() मैथड के अंदर, score ऑब्ज़र्वर कोड हटाएं.

हटाने के लिए कोड:

viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. अपने ऐप्लिकेशन को क्लीन करें, फिर से बनाएं, और चलाएं. इसके बाद, गेम खेलें. ध्यान दें कि गेम की स्क्रीन पर, मौजूदा शब्द और स्कोर को फ़ॉर्मैट किया गया है.

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

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

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

ViewModel डेटा बाइंडिंग

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

किसी लेआउट के साथ ViewModel को कैसे जोड़ा जाता है:

  • लेआउट फ़ाइल में, ViewModel टाइप का डेटा-बाइंडिंग वैरिएबल जोड़ें.
   <data>

       <variable
           name="gameViewModel"
           type="com.example.android.guesstheword.screens.game.GameViewModel" />
   </data>
  • GameFragment फ़ाइल में, GameViewModel को डेटा बाइंडिंग में पास करें.
binding.gameViewModel = viewModel

लिसनर बाइंडिंग

  • लिसनर बाइंडिंग, लेआउट में बाइंडिंग एक्सप्रेशन होते हैं. ये तब चलते हैं, जब onClick() जैसे क्लिक इवेंट ट्रिगर होते हैं.
  • लिसनर बाइंडिंग को लैम्डा एक्सप्रेशन के तौर पर लिखा जाता है.
  • लिसनर बाइंडिंग का इस्तेमाल करके, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में मौजूद क्लिक लिसनर को लेआउट फ़ाइल में मौजूद लिसनर बाइंडिंग से बदलें.
  • डेटा बाइंडिंग, एक लिसनर बनाती है और उसे व्यू पर सेट करती है.
 android:onClick="@{() -> gameViewModel.onSkip()}"

डेटा बाइंडिंग में LiveData जोड़ना

  • LiveData ऑब्जेक्ट का इस्तेमाल, डेटा-बाइंडिंग सोर्स के तौर पर किया जा सकता है. इससे डेटा में हुए बदलावों के बारे में यूज़र इंटरफ़ेस (यूआई) को अपने-आप सूचना मिल जाती है.
  • व्यू को सीधे तौर पर ViewModel में मौजूद LiveData ऑब्जेक्ट से बाइंड किया जा सकता है. ViewModel में बदलाव होने पर, लेआउट में मौजूद व्यू अपने-आप अपडेट हो सकते हैं. इसके लिए, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में ऑब्ज़र्वर के तरीकों की ज़रूरत नहीं होती.LiveData
android:text="@{gameViewModel.word}"
  • LiveData डेटा बाइंडिंग को काम करने के लिए, मौजूदा ऐक्टिविटी (यूज़र इंटरफ़ेस (यूआई) कंट्रोलर) को यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में LiveData वैरिएबल के लाइफ़साइकल के मालिक के तौर पर सेट करें.binding
binding.lifecycleOwner = this

डेटा बाइंडिंग के साथ स्ट्रिंग फ़ॉर्मैटिंग

  • डेटा बाइंडिंग का इस्तेमाल करके, स्ट्रिंग रिसॉर्स को फ़ॉर्मैट किया जा सकता है. इसके लिए, स्ट्रिंग के लिए %s और पूर्णांक के लिए %d जैसे प्लेसहोल्डर का इस्तेमाल किया जा सकता है.
  • व्यू के text एट्रिब्यूट को अपडेट करने के लिए, फ़ॉर्मैटिंग स्ट्रिंग में text ऑब्जेक्ट को आर्ग्युमेंट के तौर पर पास करें.LiveData
 android:text="@{@string/quote_format(gameViewModel.word)}"

Udacity का कोर्स:

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

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

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

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

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

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

पहला सवाल

लिसनर बाइंडिंग के बारे में इनमें से कौनसी बात सही नहीं है?

  • लिसनर बाइंडिंग, बाइंडिंग एक्सप्रेशन होते हैं. ये किसी इवेंट के होने पर चलते हैं.
  • लिसनर बाइंडिंग, Android Gradle प्लग-इन के सभी वर्शन के साथ काम करती हैं.
  • लिसनर बाइंडिंग को लैम्डा एक्सप्रेशन के तौर पर लिखा जाता है.
  • लिसनर बाइंडिंग, मेथड रेफ़रंस की तरह ही होती हैं. हालांकि, इनकी मदद से डेटा-बाइंडिंग के किसी भी एक्सप्रेशन को चलाया जा सकता है.

दूसरा सवाल

मान लें कि आपके ऐप्लिकेशन में यह स्ट्रिंग संसाधन शामिल है:
<string name="generic_name">Hello %s</string>

डेटा-बाइंडिंग एक्सप्रेशन का इस्तेमाल करके स्ट्रिंग को फ़ॉर्मैट करने के लिए, इनमें से कौनसा सिंटैक्स सही है?

  • android:text= "@{@string/generic_name(user.name)}"
  • android:text= "@{string/generic_name(user.name)}"
  • android:text= "@{@generic_name(user.name)}"
  • android:text= "@{@string/generic_name,user.name}"

तीसरा सवाल

लिसनर-बाइंडिंग एक्सप्रेशन का आकलन कब किया जाता है और इसे कब चलाया जाता है?

  • जब LiveData में मौजूद डेटा बदल जाता है
  • जब कॉन्फ़िगरेशन में बदलाव की वजह से किसी ऐक्टिविटी को फिर से बनाया जाता है
  • जब onClick() जैसा कोई इवेंट होता है
  • जब गतिविधि बैकग्राउंड में चली जाती है

अगला लेसन शुरू करें: 5.4: LiveData में बदलाव करना

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