Android Kotlin की बुनियादी जानकारी 05.3: ViewModel और LiveData के साथ डेटा बाइंडिंग

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

परिचय

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

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

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

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

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

आप इन चीज़ों के बारे में जानेंगे

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

आप क्या कर पाएंगे!

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

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

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

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

पहला खिलाड़ी सिर्फ़ शब्द बोलता हुआ सावधान रहता है.

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

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

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

गेम स्क्रीन

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

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

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

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

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

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

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

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

Button व्यू और GameViewModel सीधे तौर पर बातचीत नहीं करते—उन्हें GameFragment में मौजूद क्लिक लिसनर और #39; की ज़रूरत होती है.

View बाइंडिंग में पास किया गया 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 को डेटा बाइंडिंग में पास करें.

    ऐसा करने के लिए, binding.gameViewModel वैरिएबल को viewModel असाइन करें, जिसका एलान आपने पिछले चरण में किया था. 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() जैसे इवेंट ट्रिगर होने पर चलते हैं. लिसनर बाइंडिंग, lambda एक्सप्रेशन के तौर पर लिखी जाती हैं.

डेटा बाइंडिंग से लिसनर बनाया जाता है और व्यू पर लिसनर सेट किया जाता है. जब लिसनर-इवेंट इवेंट होता है, तब लिसनर एक्सप्रेशन का आकलन करता है. लिसनर बाइंडिंग, '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 बिल्ड पैनल के मैसेज को ध्यान से देखें. अगर आपको databinding पर खत्म होने वाली जगह की जानकारी दिखती है, तो इसका मतलब है कि डेटा बाइंडिंग के दौरान कोई गड़बड़ी हुई है.
  2. लेआउट एक्सएमएल फ़ाइल में, डेटा बाइंडिंग का इस्तेमाल करने वाली onClick एट्रिब्यूट में मौजूद गड़बड़ियों की जांच करें. Lambda के एक्सप्रेशन से जुड़े फ़ंक्शन को ढूंढें और पक्का करें कि वह मौजूद है.
  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

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

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

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

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

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

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

<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. अपना ऐप्लिकेशन चलाएं और गेम खेलें. अब यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में ऑब्ज़र्वर मेथड के बिना, मौजूदा शब्द अपडेट किया जा रहा है.

दूसरा चरण: स्कोर_फ़्रैगमेंट.xml फ़ाइल में स्कोर का 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. quote_format स्ट्रिंग रिसॉर्स का इस्तेमाल करने के लिए, game_fragment.xml में 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

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

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

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

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

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

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

Udcity कोर्स:

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

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

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

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

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

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

पहला सवाल

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

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

दूसरा सवाल

मान लें कि आपके ऐप्लिकेशन में यह स्ट्रिंग रिसॉर्स शामिल है:
<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 की बुनियादी बातें कोडलैब का लैंडिंग पेज देखें.