यह कोडलैब Android Kotlin के बुनियादी कोर्स में शामिल है. अगर आप कोडलैब के क्रम में काम करते हैं, तो आपको इस कोर्स का ज़्यादा से ज़्यादा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Android Kotlin से जुड़े बेसिक कोडलैब के लैंडिंग पेज पर दिए गए हैं.
परिचय
पिछले कोडलैब में, आप GuessTheWord ऐप्लिकेशन में ViewModel
का इस्तेमाल करते थे, ताकि ऐप्लिकेशन के डेटा में डिवाइस कॉन्फ़िगरेशन के हिसाब से बदलाव होते रहें. इस कोडलैब में, आप LiveData
को ViewModel
क्लास के डेटा के साथ इंटिग्रेट करने का तरीका जान सकते हैं. LiveData
, जो Android आर्किटेक्चर कॉम्पोनेंट में से एक है. इसकी मदद से, आप डेटाबेस के डेटा में बदलाव होने पर, व्यू के बारे में जानकारी देने वाले डेटा ऑब्जेक्ट बना सकते हैं.
LiveData
क्लास का इस्तेमाल करने के लिए, आप &कोटेशन;कोटेशन (उदाहरण के लिए, गतिविधियां या फ़्रैगमेंट) सेट अप करते हैं, जो ऐप्लिकेशन के डेटा में होने वाले बदलावों पर नज़र रखते हैं. LiveData
, लाइफ़साइकल की जानकारी देता है. इसलिए, यह सिर्फ़ ऐप्लिकेशन के कॉम्पोनेंट के ऑब्ज़र्वर को अपडेट करता है, जो लाइफ़साइकल की चालू स्थिति में हैं.
आपको क्या पता होना चाहिए
- Kotlin में बेसिक Android ऐप्लिकेशन बनाने का तरीका.
- अपने ऐप्लिकेशन के डेस्टिनेशन के बीच नेविगेट करने का तरीका.
- फ़्रैगमेंट और गतिविधि पूरी होने की प्रोसेस (लाइफ़साइकल).
- अपने ऐप्लिकेशन में
ViewModel
ऑब्जेक्ट इस्तेमाल करने का तरीका. ViewModelProvider.Factory
इंटरफ़ेस का इस्तेमाल करके,ViewModel
ऑब्जेक्ट बनाने का तरीका.
आप इन चीज़ों के बारे में जानेंगे
LiveData
ऑब्जेक्ट कैसे काम के होते हैं.ViewModel
में सेव किए गए डेटा मेंLiveData
जोड़ने का तरीका.MutableLiveData
को कब और कैसे इस्तेमाल करना चाहिए.LiveData.
में होने वाले बदलावों को देखने के लिए, ऑब्ज़र्वर के तरीकों को कैसे जोड़ें- बैकिंग प्रॉपर्टी का इस्तेमाल करके
LiveData
को कैसे एनकैप्सुलेट करें. - यूज़र इंटरफ़ेस (यूआई) कंट्रोलर और उससे जुड़े
ViewModel
के बीच बातचीत करने का तरीका.
आप क्या कर पाएंगे!
- शब्द और GuessTheWord ऐप्लिकेशन में स्कोर के लिए
LiveData
का उपयोग करें. - ऑब्ज़र्वर जोड़ें जो शब्द या स्कोर में बदलाव होने पर सूचना देते हों.
- वे टेक्स्ट व्यू अपडेट करें जो बदली गई वैल्यू दिखाते हैं.
- गेम के खास इवेंट को जोड़ने के लिए,
LiveData
ऑब्ज़र्वर पैटर्न का इस्तेमाल करें. - फिर से चलाएं बटन लागू करें.
लेसन 5 कोडलैब में, आप GuessTheWord ऐप्लिकेशन डेवलप करते हैं. इसकी शुरुआत स्टार्टर कोड से होती है. GuessTheWord दो-खिलाड़ियों वाला चार्टेस-शैली का गेम है, जिसमें खिलाड़ी सबसे ज़्यादा स्कोर हासिल करने के लिए मिलकर काम करते हैं.
पहला खिलाड़ी ऐप्लिकेशन में शब्दों को देखता है और हर एक को एक-एक करके करता है, ताकि यह पक्का हो सके कि वह दूसरे खिलाड़ी को शब्द न दिखाए. दूसरा खिलाड़ी, शब्द का अनुमान लगाने की कोशिश करता है.
गेम खेलने के लिए, पहला खिलाड़ी डिवाइस पर ऐप्लिकेशन खोलता है और एक शब्द देखता है, उदाहरण के लिए, " गिटार,&कोटेशन; जैसा कि नीचे स्क्रीनशॉट में दिखाया गया है.
पहला खिलाड़ी सिर्फ़ शब्द बोलता हुआ सावधान रहता है.
- जब दूसरा खिलाड़ी शब्द का सही अनुमान लगाता है, तो पहला खिलाड़ी ठीक है बटन दबाता है. इससे बटन की संख्या एक बढ़ जाती है और अगला शब्द दिखता है.
- अगर दूसरा खिलाड़ी शब्द का अनुमान नहीं लगा सकता, तो पहला खिलाड़ी छोड़ें बटन को दबाता है. इससे एक शब्द कम हो जाता है और अगले शब्द पर चला जाता है.
- गेम खत्म करने के लिए, गेम खत्म करें बटन दबाएं. (यह सुविधा सीरीज़ के पहले कोडलैब (कोड बनाना सीखना) के स्टार्टर कोड में't है.)
इस कोडलैब में, जब उपयोगकर्ता ऐप्लिकेशन में सभी शब्दों के बीच साइकल चलाता है, तब आप गेम खत्म करने के लिए एक इवेंट जोड़कर, GuessTheWord ऐप्लिकेशन को बेहतर बनाते हैं. आप स्कोर फ़्रैगमेंट में फिर से चलाएं बटन भी जोड़ते हैं, ताकि उपयोगकर्ता फिर से गेम खेल सके.
शीर्षक स्क्रीन | गेम स्क्रीन | स्कोर स्क्रीन |
इस टास्क में, आप इस कोडलैब के लिए अपने स्टार्टर कोड का पता लगाते हैं और उसे चलाते हैं. आप पिछले कोडलैब (कोड बनाना सीखना) में बनाए गए GuessTheWord ऐप्लिकेशन को अपने स्टार्टर कोड के तौर पर इस्तेमाल कर सकते हैं या फिर आप एक स्टार्टर ऐप्लिकेशन डाउनलोड कर सकते हैं.
- (ज़रूरी नहीं) अगर आप पिछले कोडलैब से कोड का इस्तेमाल नहीं कर रहे हैं, तो इस कोडलैब के लिए स्टार्टर कोड डाउनलोड करें. कोड को अनज़िप करें और प्रोजेक्ट को Android Studio में खोलें.
- ऐप्लिकेशन चलाएं और गेम खेलें.
- ध्यान दें कि अभी नहीं बटन अगले शब्द को दिखाता है और स्कोर में एक की कमी कर देता है. वहीं, ठीक है बटन अगला शब्द दिखाता है और स्कोर को एक बढ़ा देता है. गेम खत्म करें बटन से गेम खत्म हो जाता है.
LiveData
निगरानी करने वाला ऐसा डेटा क्लास है जिसे लाइफ़साइकल के बारे में पता है. उदाहरण के लिए, आप GuessTheWord ऐप्लिकेशन में मौजूदा स्कोर के आस-पास LiveData
रैप कर सकते हैं. इस कोडलैब में, आप LiveData
की कई विशेषताओं के बारे में जान सकते हैं:
LiveData
की निगरानी की जा सकती है. इसका मतलब है कि जबLiveData
ऑब्जेक्ट का डेटा बदलता है, तो ऑब्ज़र्वर को इसकी सूचना दी जाती है.LiveData
के पास डेटा है;LiveData
एक रैपर है जिसे किसी भी डेटा के साथ इस्तेमाल किया जा सकता हैLiveData
, लाइफ़साइकल की जानकारी देता है. इसका मतलब है कि सिर्फ़ उन ऑब्ज़र्वर को अपडेट करता है जोSTARTED
याRESUMED
जैसी किसी चालू लाइफ़साइकल की स्थिति में हैं.
इस टास्क में, किसी भी तरह के डेटा को LiveData
ऑब्जेक्ट में रैप करने का तरीका जानें. इसके लिए, मौजूदा स्कोर और मौजूदा शब्द के डेटा को GameViewModel
में बदलें. इसके लिए, चुनें. बाद के टास्क में, LiveData
ऑब्जेक्ट में ऑब्ज़र्वर जोड़ा जाता है और LiveData
के बारे में जानने का तरीका जाना जाता है.
पहला चरण: LiveData का इस्तेमाल करने के लिए स्कोर और शब्द बदलना
screens/game
पैकेज में,GameViewModel
फ़ाइल खोलें.- वैरिएबल
score
औरword
का टाइप बदलकरMutableLiveData
करें.MutableLiveData
,LiveData
है जिसका मान बदला जा सकता है.MutableLiveData
एक जेनरिक क्लास है, इसलिए आपको यह बताना होगा कि यह किस तरह का डेटा है.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
GameViewModel
में,init
ब्लॉक में,score
औरword
शुरू करें.LiveData
वैरिएबल की वैल्यू बदलने के लिए, वैरिएबल मेंsetValue()
तरीके का इस्तेमाल करें. Kotlin में, आपvalue
प्रॉपर्टी का इस्तेमाल करकेsetValue()
को कॉल कर सकते हैं.
init {
word.value = ""
score.value = 0
...
}
दूसरा चरण: LiveData ऑब्जेक्ट के रेफ़रंस को अपडेट करना
अब score
और word
वैरिएबल, LiveData
टाइप के हैं. इस चरण में, value
प्रॉपर्टी का इस्तेमाल करके, इन वैरिएबल के रेफ़रंस बदलें.
GameViewModel
केonSkip()
तरीके में,score
कोscore.value
में बदलें.score
के शायदnull
होने की गड़बड़ी देखें. इसके बाद, आप इस गड़बड़ी को ठीक करते हैं.- गड़बड़ी को ठीक करने के लिए,
onSkip()
मेंnull
चेक कोscore.value
में जोड़ें. फिरscore
परminus()
फ़ंक्शन को कॉल करें, जोnull
-safety के साथ घटाता है.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}
onCorrect()
तरीके को इसी तरह अपडेट करें:score
वैरिएबल मेंnull
चेक जोड़ें औरplus()
फ़ंक्शन का इस्तेमाल करें.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}
GameViewModel
में,nextWord()
के तरीके में,word
रेफ़रंस कोword
.
value
में बदलें.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
GameFragment
में,updateWordText()
के तरीके में, रेफ़रंस कोviewModel
.word
से बदलकरviewModel
.
word
.
value.
करें
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
GameFragment
में,updateScoreText()
के तरीके में, रेफ़रंस काviewModel
.score
से बदलकरviewModel
.
score
.
value.
करें
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
GameFragment
में,gameFinished()
तरीके के अंदर, रेफ़रंस कोviewModel
.score
सेviewModel
.
score
.
value
में बदलें. ज़रूरीnull
सुरक्षा जांच जोड़ें.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
NavHostFragment.findNavController(this).navigate(action)
}
- पक्का करें कि आपके कोड में कोई गड़बड़ी न हो. अपना ऐप्लिकेशन कंपाइल करें और चलाएं. ऐप्लिकेशन का फ़ंक्शन पहले जैसा ही होना चाहिए.
यह टास्क, पिछले टास्क से मिलता-जुलता है. इसमें आपने स्कोर और शब्द का डेटा, LiveData
ऑब्जेक्ट में बदला था. इस टास्क में, आप Observer
ऑब्जेक्ट को उन LiveData
ऑब्जेक्ट में अटैच करते हैं.
GameFragment,
मेंonCreateView()
तरीके से, मौजूदा स्कोरviewModel.score
के लिए,LiveData
ऑब्जेक्ट में एकObserver
ऑब्जेक्ट अटैच करें.observe()
तरीके का इस्तेमाल करें औरviewModel
के शुरू होने के बाद कोड डालें. कोड को आसान बनाने के लिए Lambda के एक्सप्रेशन का इस्तेमाल करें. (lambda एक्सप्रेशन एक ऐसा फ़ंक्शन है जिसकी पहचान ज़ाहिर नहीं की जाती और जिसे #33 नहीं बताया जाता, लेकिन इसे एक्सप्रेशन के तौर पर तुरंत पास किया जाता है.
viewModel.score.observe(this, Observer { newScore ->
})
Observer
का रेफ़रंस दें. ऐसा करने के लिए, Observer
पर क्लिक करें, Alt+Enter
(Mac पर Option+Enter
) दबाएं, और androidx.lifecycle.Observer
इंपोर्ट करें.
- आपके बनाए गए ऑब्ज़र्वर को तब एक इवेंट मिलता है, जब ऑब्ज़र्व किए गए
LiveData
ऑब्जेक्ट का डेटा बदलता है. ऑब्ज़र्वर के अंदर, नए स्कोर सेTextView
का स्कोर अपडेट करें.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
Observer
शब्द को मौजूदा शब्दLiveData
ऑब्जेक्ट में अटैच करें. इसे ठीक उसी तरह करें, जैसे आप मौजूदा स्कोर मेंObserver
ऑब्जेक्ट जोड़ते हैं.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
binding.wordText.text = newWord
})
score
या word
की वैल्यू में बदलाव होने पर, स्क्रीन पर दिखने वाली score
या word
अपने-आप अपडेट हो जाती है.
GameFragment
में,updateWordText()
औरupdateScoreText()
के तरीके और उनसे जुड़े सभी रेफ़रंस मिटाएं. आपको अब इनकी ज़रूरत नहीं है, क्योंकि टेक्स्ट व्यू की निगरानी,LiveData
ऑब्ज़र्वर मेथड करते हैं.- अपना ऐप्लिकेशन चलाएं. आपका गेम ऐप्लिकेशन पहले की तरह ही काम करेगा, लेकिन अब वह
LiveData
औरLiveData
ऑब्ज़र्वर का इस्तेमाल करता है.
एनकैप्सुलेशन किसी ऑब्जेक्ट के कुछ ऐक्सेस को सीमित करने का एक तरीका है#2. जब आप किसी ऑब्जेक्ट को एनकैप्सुलेट करते हैं, तो आप सार्वजनिक अंदरूनी फ़ील्ड में बदलाव करने वाले सार्वजनिक तरीकों का सेट दिखाते हैं. एनकैप्सुलेशन का इस्तेमाल करके, आप यह कंट्रोल करते हैं कि अन्य क्लास इन अंदरूनी फ़ील्ड में हेर-फेर कैसे करें.
आपके मौजूदा कोड में, कोई भी बाहरी क्लास, value
प्रॉपर्टी का इस्तेमाल करके score
और word
वैरिएबल में बदलाव कर सकती है, उदाहरण के लिए viewModel.score.value
का इस्तेमाल करना. यह ज़रूरी नहीं है कि आप इस कोडलैब में डेवलप किए जा रहे ऐप्लिकेशन में ज़रूरी हों, लेकिन प्रोडक्शन ऐप्लिकेशन में जाकर, ViewModel
ऑब्जेक्ट के डेटा को कंट्रोल करना चाहते हैं.
सिर्फ़ आपके ऐप्लिकेशन के डेटा में ViewModel
बदलाव करना चाहिए. हालांकि, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर को डेटा पढ़ने की ज़रूरत होती है, ताकि डेटा फ़ील्ड पूरी तरह से निजी हो सकें. अपने ऐप्लिकेशन के डेटा को एनकैप्सुलेट करने के लिए, MutableLiveData
और LiveData
ऑब्जेक्ट, दोनों का इस्तेमाल किया जाता है.
MutableLiveData
बनाम LiveData
:
MutableLiveData
ऑब्जेक्ट में डेटा को बदला जा सकता है, जैसा कि नाम से पता चलता है.ViewModel
के अंदर, डेटा में बदलाव किया जा सकता है, इसलिए वहMutableLiveData
का इस्तेमाल करता है.LiveData
ऑब्जेक्ट में मौजूद डेटा को पढ़ा जा सकता है, लेकिन उसे बदला नहीं जा सकता.ViewModel
के बाहर से, डेटा पढ़ने लायक होना चाहिए, लेकिन उसमें बदलाव नहीं किया जा सकता. इसलिए, डेटाLiveData
के तौर पर दिखाया जाना चाहिए.
इस रणनीति को पूरा करने के लिए, आप Kotlin बैकिंग प्रॉपर्टी का इस्तेमाल करते हैं. बैकिंग प्रॉपर्टी से आप सही ऑब्जेक्ट के बजाय, गैटर से कुछ लौटा सकते हैं. इस टास्क में, आप GuessTheWord ऐप्लिकेशन में score
और word
ऑब्जेक्ट के लिए, एक बैकिंग प्रॉपर्टी लागू करते हैं.
स्कोर और शब्द का इस्तेमाल करने के लिए, बैकिंग प्रॉपर्टी जोड़ें
GameViewModel
में, मौजूदाscore
ऑब्जेक्ट कोprivate
बनाएं.- बैकिंग प्रॉपर्टी में इस्तेमाल किए जाने वाले नाम के नियम का पालन करने के लिए,
score
को_score
में बदलें._score
प्रॉपर्टी अब गेम स्कोर का बदलाव करने लायक वर्शन है, जिसका इस्तेमाल आंतरिक रूप से किया जाएगा. LiveData
प्रकार का सार्वजनिक वर्शन बनाएं, जिसेscore
कहते हैं.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
- आपको शुरू करने में कोई गड़बड़ी हुई. यह गड़बड़ी इसलिए होती है, क्योंकि
GameFragment
मेंscore
,LiveData
पहचान फ़ाइल है औरscore
अब इसके सेटर को ऐक्सेस नहीं कर सकता. Kotlin में गैटर और सेटर के बारे में ज़्यादा जानने के लिए, Getter and Setters को देखें.
इस गड़बड़ी को ठीक करने के लिए,GameViewModel
मेंscore
ऑब्जेक्ट के लिए,get()
के तरीके को बदलें और बैकिंग प्रॉपर्टी_score
पर जाएं.
val score: LiveData<Int>
get() = _score
GameViewModel
में,score
की पहचान फ़ाइलों को बदलकर उसके अंदरूनी_score
वर्शन का इस्तेमाल करें.
init {
...
_score.value = 0
...
}
...
fun onSkip() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.minus(1)
}
...
}
fun onCorrect() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.plus(1)
}
...
}
word
ऑब्जेक्ट का नाम बदलकर_word
करें और इसके लिए कोई बैकिंग प्रॉपर्टी जोड़ें, जैसा कि आपनेscore
ऑब्जेक्ट के लिए किया था.
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word
...
init {
_word.value = ""
...
}
...
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
_word.value = wordList.removeAt(0)
}
}
बहुत बढ़िया, आपने #LiveData
ऑब्जेक्ट को word
और score
में रख दिया है.
जब उपयोगकर्ता गेम खत्म करें बटन पर टैप करता है, तो आपका मौजूदा ऐप्लिकेशन स्कोर स्क्रीन पर जाता है. जब खिलाड़ी सभी शब्दों पर गौर करें, तो ऐप्लिकेशन को स्कोर स्क्रीन पर भी ले जाना चाहिए. जब खिलाड़ी आखिरी शब्द पूरी कर लेता है, तब आप चाहते हैं कि गेम अपने-आप खत्म हो जाए, ताकि उपयोगकर्ता बटन पर टैप न करे.
इस सुविधा को लागू करने के लिए, आपको एक इवेंट ट्रिगर करना होगा. इसके लिए, जब सभी शब्द दिखाए जाएंगे, तब ViewModel
का फ़्रैगमेंट बताया जाएगा. ऐसा करने के लिए, आप LiveData
गेम का इस्तेमाल करने वाले इवेंट के लिए, ऑब्ज़र्वर पैटर्न का इस्तेमाल करते हैं.
ऑब्ज़र्वर पैटर्न
ऑब्ज़र्वर पैटर्न एक सॉफ़्टवेयर डिज़ाइन पैटर्न है. इससे ऑब्जेक्ट के बीच कम्यूनिकेशन के बारे में पता चलता है: ऑब्ज़र्व किया जा सकने वाला और && ऑब्ज़र्वर. ऑब्ज़र्व किया जा सकने वाला वह ऑब्जेक्ट होता है जो ऑब्ज़र्वर को अपनी स्थिति में बदलावों के बारे में सूचना देता है.
इस ऐप्लिकेशन में LiveData
के मामले में, ऑब्ज़र्व किया जा सकने वाला (विषय) LiveData
ऑब्जेक्ट है. साथ ही, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में ऑब्ज़र्वर जैसे फ़्रैगमेंट होते हैं. जब भी LiveData
का डेटा बदलता है, तो उसकी स्थिति में बदलाव होता है. ViewModel
से फ़्रैगमेंट तक बात करने के लिए, LiveData
क्लास ज़रूरी हैं.
पहला चरण: गेम खत्म होने के इवेंट का पता लगाने के लिए, LiveData का इस्तेमाल करना
इस टास्क में, आप गेम के पूरे होने वाले इवेंट का मॉडल बनाने के लिए, LiveData
ऑब्ज़र्वर पैटर्न का इस्तेमाल करते हैं.
GameViewModel
में,_eventGameFinish
नाम का एकBoolean
MutableLiveData
ऑब्जेक्ट बनाएं. इस ऑब्जेक्ट में गेम खत्म होने वाला इवेंट होगा._eventGameFinish
ऑब्जेक्ट शुरू करने के बाद,eventGameFinish
नाम वाली बैकिंग प्रॉपर्टी बनाएं और उसे शुरू करें.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
GameViewModel
में,onGameFinish()
का कोई तरीका जोड़ें. इस तरीके में, गेम खत्म होने के इवेंट,eventGameFinish
कोtrue
पर सेट करें.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
GameViewModel
में, अगरnextWord()
सूची में कोई शब्द नहीं है, तो गेम को खत्म करें.
private fun nextWord() {
if (wordList.isEmpty()) {
onGameFinish()
} else {
//Select and remove a _word from the list
_word.value = wordList.removeAt(0)
}
}
GameFragment
में,onCreateView()
के अंदर,viewModel
में,eventGameFinish
पर ऑब्ज़र्वर को जोड़ें.observe()
वाले तरीके का इस्तेमाल करें. Lambda के फ़ंक्शन के अंदर,gameFinished()
तरीके को कॉल करें.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})
- अपना ऐप्लिकेशन चलाएं, गेम खेलें, और सभी शब्द देखें. जब तक आप गेम बंद करें पर टैप नहीं करते, तब तक ऐप्लिकेशन, फ़्रैगमेंट में ही रहने के बजाय, स्कोर स्क्रीन पर अपने-आप चला जाता है.
शब्द की सूची खाली होने के बाद,eventGameFinish
सेट हो जाता है, गेम फ़्रैगमेंट में ऑब्ज़र्वर का तरीका कॉल किया जाता है, और ऐप्लिकेशन स्क्रीन फ़्रैगमेंट पर नेविगेट करता है. - जोड़े गए कोड की वजह से, लाइफ़साइकल की समस्या ठीक हो गई है. इस समस्या को समझने के लिए,
GameFragment
क्लास में,gameFinished()
तरीके में दिए गए नेविगेशन कोड पर टिप्पणी करें.Toast
मैसेज को तरीके में रखें.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
// val action = GameFragmentDirections.actionGameToScore()
// action.score = viewModel.score.value?:0
// NavHostFragment.findNavController(this).navigate(action)
}
- अपना ऐप्लिकेशन चलाएं, गेम खेलें, और सभी शब्द देखें. टोस्ट मैसेज, जिसमें यह बताया गया है कि "गेम अभी खत्म हुआ है", गेम स्क्रीन के सबसे नीचे दिखता है. इससे पता चलता है कि गेम चालू है.
अब डिवाइस या एम्युलेटर को घुमाएं. टोस्ट फिर से दिखाई देता है! डिवाइस को कई बार घुमाएं और हर बार टोस्ट दिखाई देगा. यह एक गड़बड़ी है, क्योंकि टोस्ट सिर्फ़ एक बार दिखना चाहिए, जब गेम खत्म हो जाएगा. फ़्रैगमेंट के फिर से बनाए जाने पर, टोस्ट हर बार नहीं दिखना चाहिए. आप अगले टास्क में इस समस्या को ठीक कर देंगे.
दूसरा चरण: गेम खत्म होने के इवेंट को रीसेट करना
आम तौर पर, डेटा में बदलाव होने पर ही, LiveData
ऑब्ज़र्वर को अपडेट डिलीवर किए जाते हैं. इस व्यवहार का एक अपवाद यह है कि जब ऑब्ज़र्वर चालू से किसी चालू स्थिति में बदलते हैं, तो ऑब्ज़र्वर को भी अपडेट मिलते हैं.
इसी वजह से, गेम में तैयार टोस्ट को आपके ऐप्लिकेशन में बार-बार ट्रिगर किया जाता है. जब स्क्रीन को घुमाने के बाद, गेम फ़्रैगमेंट को फिर से बनाया जाता है, तब वह बंद से चालू स्थिति में चला जाता है. फ़्रैगमेंट में ऑब्ज़र्वर मौजूदा ViewModel
से फिर से कनेक्ट होता है और मौजूदा डेटा लेता है. gameFinished()
तरीके को फिर से ट्रिगर किया जाता है और टोस्ट दिखता है.
इस टास्क में, आप GameViewModel
में eventGameFinish
का फ़्लैग रीसेट करके, इस समस्या को ठीक करते हैं और टोस्ट सिर्फ़ एक बार दिखाते हैं.
GameViewModel
में, गेम खत्म होने के इवेंट_eventGameFinish
को रीसेट करने के लिए,onGameFinishComplete()
का तरीका जोड़ें.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
GameFragment
में,gameFinished()
के आखिर में,viewModel
ऑब्जेक्ट परonGameFinishComplete()
को कॉल करें. (gameFinished()
में नेविगेशन कोड पर अभी टिप्पणी की गई है.)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- ऐप्लिकेशन चलाएं और गेम खेलें. सभी शब्दों को पढ़ने के बाद, डिवाइस की स्क्रीन की दिशा बदलें. टोस्ट सिर्फ़ एक बार दिखाया जाता है.
GameFragment
में,gameFinished()
तरीके में जाकर नेविगेशन कोड को अनटिप्पणी करें.
Android Studio में टिप्पणी करने से रोकने के लिए, वे लाइनें चुनें जिन पर टिप्पणी की जाती है औरControl+/
(Mac परCommand+/
) दबाएं.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
findNavController(this).navigate(action)
viewModel.onGameFinishComplete()
}
अगर Android Studio से पूछा जाए, तो androidx.navigation.fragment.NavHostFragment.findNavController
इंपोर्ट करें.
- ऐप्लिकेशन चलाएं और गेम खेलें. यह पक्का करें कि सभी शब्दों को देखने के बाद, ऐप्लिकेशन अपने-आप फ़ाइनल स्कोर स्क्रीन पर चला जाए.
बहुत बढ़िया! आपका ऐप्लिकेशन, LiveData
का इस्तेमाल करके, GameViewModel
से उस गेम के फ़्रैगमेंट को अपडेट करेगा, जिसके लिए शब्द सूची खाली है. इसके बाद, गेम फ़्रैगमेंट, स्कोर फ़्रैगमेंट पर जाता है.
इस टास्क में, आप स्कोर को ScoreViewModel
में LiveData
ऑब्जेक्ट में बदलते हैं और उसमें ऑब्ज़र्वर अटैच करते हैं. यह टास्क वैसा ही है जैसा आपने GameViewModel
में LiveData
जोड़ते समय किया था.
आप ScoreViewModel
को पूरा बनाने के लिए ये बदलाव करते हैं, ताकि आपके ऐप्लिकेशन का पूरा डेटा LiveData
का इस्तेमाल करे.
ScoreViewModel
में,score
वैरिएबल टाइप कोMutableLiveData
में बदलें. नाम के हिसाब से नाम बदलें_score
और उसमें बैकिंग प्रॉपर्टी जोड़ें.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
ScoreViewModel
में,init
ब्लॉक के अंदर,_score
शुरू करें. आपinit
ब्लॉक में लॉग को मनमुताबिक छोड़ या छोड़ सकते हैं.
init {
_score.value = finalScore
}
ScoreFragment
में,onCreateView()
में,viewModel
शुरू करने के बाद, स्कोरLiveData
ऑब्जेक्ट के लिए ऑब्ज़र्वर अटैच करें. Lambda के एक्सप्रेशन में, स्कोर की वैल्यू को स्कोर के टेक्स्ट व्यू पर सेट करें. वह कोड हटाएं जोViewModel
से स्कोर वैल्यू के साथ टेक्स्ट व्यू को सीधे असाइन करता है.
यह कोड जोड़ें:
// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
हटाया जाने वाला कोड:
binding.scoreText.text = viewModel.score.toString()
Android Studio के अनुरोध पर, androidx.lifecycle.Observer
इंपोर्ट करें.
- अपना ऐप्लिकेशन चलाएं और गेम खेलें. ऐप्लिकेशन को पहले की तरह काम करना चाहिए, लेकिन अब स्कोर को अपडेट करने के लिए
LiveData
और ऑब्ज़र्वर का इस्तेमाल करता है.
इस टास्क में, आप स्कोर स्क्रीन पर फिर से चलाएं बटन जोड़ते हैं और LiveData
इवेंट का इस्तेमाल करके, क्लिक लिसनर लागू करते हैं. यह बटन, इवेंट को स्कोर स्क्रीन से गेम स्क्रीन पर नेविगेट करने के लिए ट्रिगर करता है.
ऐप्लिकेशन के स्टार्टर कोड में फिर से चलाएं बटन शामिल होता है, लेकिन बटन छिपा हुआ होता है.
res/layout/score_fragment.xml
में,play_again_button
बटन के लिए,visibility
एट्रिब्यूट' की वैल्यू कोvisible
में बदलें.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>
ScoreViewModel
में,LiveData
ऑब्जेक्ट जोड़ें. इसके बाद,_eventPlayAgain
नाम केBoolean
को होल्ड किया जा सकेगा. इस ऑब्जेक्ट का इस्तेमालLiveData
इवेंट को सेव करने के लिए किया जाता है, ताकि स्कोर स्क्रीन से गेम स्क्रीन पर भेजा जा सके.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
ScoreViewModel
में, इवेंट सेट करने और रीसेट करने के तरीके,_eventPlayAgain
तय करें.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
ScoreFragment
में,eventPlayAgain
के लिए ऑब्ज़र्वर जोड़ें. कोड कोreturn
स्टेटमेंट के पहले,onCreateView()
के आखिर में रखें. Lambda के एक्सप्रेशन में, गेम स्क्रीन पर वापस जाएं औरeventPlayAgain
को रीसेट करें.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
if (playAgain) {
findNavController().navigate(ScoreFragmentDirections.actionRestart())
viewModel.onPlayAgainComplete()
}
})
Android Studio की मदद से, androidx.navigation.fragment.findNavController
का मैसेज मिलने पर इंपोर्ट करें.
ScoreFragment
में,onCreateView()
में जाकर, PlayAgain बटन में क्लिक लिसनर जोड़ें औरviewModel
.onPlayAgain()
को कॉल करें.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }
- अपना ऐप्लिकेशन चलाएं और गेम खेलें. गेम के खत्म होने पर, स्कोर स्क्रीन से फ़ाइनल स्कोर और फिर से चलाएं बटन दिखता है. PlayAgain बटन पर टैप करें और ऐप्लिकेशन गेम स्क्रीन पर नेविगेट कर देगा, ताकि आप गेम फिर से खेल सकें.
बढ़िया! आपने ViewModel
में LiveData
ऑब्जेक्ट का इस्तेमाल करने के लिए, अपने ऐप्लिकेशन का आर्किटेक्चर बदल दिया है. साथ ही, आपने LiveData
ऑब्जेक्ट में ऑब्ज़र्वर को अटैच किया है. जब LiveData
की वैल्यू में बदलाव होता है, तो LiveData
ऑब्ज़र्वर ऑब्जेक्ट को सूचना देता है.
Android Studio प्रोजेक्ट: GuessTheWord
LiveData
LiveData
निगरानी करने वाला ऐसा डेटा होल्डर है जिसे लाइफ़साइकल की जानकारी मिलती है. यह Android आर्किटेक्चर के कॉम्पोनेंट में से एक है.- डेटा अपडेट होने पर, यूज़र इंटरफ़ेस (यूआई) को अपने-आप अपडेट करने के लिए
LiveData
का इस्तेमाल किया जा सकता है. LiveData
की निगरानी की जा सकती है. इसका मतलब है कि गतिविधि या फ़्रैगमेंट जैसे ऑब्ज़र्वर को सूचना दी जा सकती है. ऐसा तब होता है, जबLiveData
ऑब्जेक्ट का डेटा बदल जाता है.LiveData
में डेटा होता है; यह एक रैपर है, जिसका इस्तेमाल किसी भी डेटा के साथ किया जा सकता है.LiveData
, लाइफ़साइकल की जानकारी देता है. इसका मतलब है कि सिर्फ़ उन ऑब्ज़र्वर को अपडेट करता है जोSTARTED
याRESUMED
जैसी किसी चालू लाइफ़साइकल की स्थिति में हैं.
LiveData जोड़ने के लिए
ViewModel
में डेटा वैरिएबल टाइप कोLiveData
याMutableLiveData
में बदलें.
MutableLiveData
एक LiveData
ऑब्जेक्ट है जिसका मान बदला जा सकता है. MutableLiveData
एक जेनरिक क्लास है, इसलिए आपको यह बताना होगा कि यह किस तरह का डेटा है.
LiveData
के होल्ड किए गए डेटा का मान बदलने के लिए,LiveData
वैरिएबल परsetValue()
तरीका इस्तेमाल करें.
LiveData एनकैप्सुलेट करने के लिए
ViewModel
के अंदरLiveData
में बदलाव किया जाना चाहिए.ViewModel
के बाहर,LiveData
पढ़ा जा सकने वाला होना चाहिए. Kotlin बैकिंग प्रॉपर्टी का इस्तेमाल करके इसे लागू किया जा सकता है.- Kotlin की बैकिंग प्रॉपर्टी की मदद से आप पूरी तरह इस्तेमाल किए गए ऑब्जेक्ट के अलावा, गैटर से कुछ रिटर्न कर सकते हैं.
LiveData
को इनकैप्सुलेट करने के लिए,ViewModel
मेंprivate
MutableLiveData
का इस्तेमाल करें औरViewModel
के बाहरLiveData
बैक अप प्रॉपर्टी वापस करें.
ऑब्ज़र्व किया जा सकने वाला LiveData
LiveData
, ऑब्ज़र्वर पैटर्न को फ़ॉलो करता है. &कोटेशन की निगरानी वाला कोटेशन एकLiveData
ऑब्जेक्ट है. यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में, ऑब्ज़र्वर जैसे फ़्रैगमेंट होते हैं. जब भीLiveData
में रैप किया गया डेटा बदलता है, तो यूज़र इंटरफ़ेस (यूआई) कंट्रोलर की निगरानी के तरीके सूचना दी जाती हैं.LiveData
को निगरानी करने लायक बनाने के लिए,observe()
तरीके का इस्तेमाल करके, ऑब्ज़र्वर मेंLiveData
ऑब्ज़र्वर (जैसे कि ऐक्टिविटी और फ़्रैगमेंट) को जोड़ें.LiveData
ऑब्ज़र्वर पैटर्न का इस्तेमाल,ViewModel
से यूज़र इंटरफ़ेस (यूआई) कंट्रोलर से संपर्क करने के लिए किया जा सकता है.
Udcity कोर्स:
Android डेवलपर दस्तावेज़:
- ViewModel की खास जानकारी
- LiveData के बारे में खास जानकारी
MutableLiveData
- ऐप्लिकेशन के आर्किटेक्चर की गाइड
अन्य:
- Kotlin में बैकिंग प्रॉपर्टी
इस सेक्शन में उन छात्र-छात्राओं के लिए गृहकार्य की असाइनमेंट की सूची दी गई है जो इस कोडलैब के ज़रिए एक शिक्षक की देखरेख में कोर्स में काम कर रहे हैं. यह क्रिएटर का काम #33 पर निर्भर करता है:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को होमवर्क के असाइनमेंट सबमिट करने के तरीके के बारे में बताएं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल जितनी चाहें उतनी कम या ज़्यादा कर सकते हैं. साथ ही, उन्हें अपने हिसाब से कोई भी होमवर्क असाइन करना चाहिए.
अगर आप इस कोडलैब के ज़रिए खुद काम कर रहे हैं, तो बेझिझक इन होमवर्क असाइनमेंट का इस्तेमाल करें.
इन सवालों के जवाब दें
पहला सवाल
आप ViewModel
में सेव किए गए LiveData
को कैसे एनकैप्सुलेट करते हैं, ताकि बाहरी ऑब्जेक्ट अपडेट किए बिना डेटा को पढ़ सकें?
ViewModel
ऑब्जेक्ट में, डेटा का डेटा टाइप बदलकरprivate
LiveData
करें. टाइपMutableLiveData
का रीड ओनली डेटा दिखाने के लिए, बैकिंग प्रॉपर्टी का इस्तेमाल करें.ViewModel
ऑब्जेक्ट में, डेटा का डेटा टाइप बदलकरprivate
MutableLiveData
करें. टाइपLiveData
का रीड ओनली डेटा दिखाने के लिए, बैकिंग प्रॉपर्टी का इस्तेमाल करें.- यूज़र इंटरफ़ेस (यूआई) कंट्रोलर के अंदर, डेटा के डेटा टाइप को बदलकर
private
MutableLiveData
करें. टाइपLiveData
का रीड ओनली डेटा दिखाने के लिए, बैकिंग प्रॉपर्टी का इस्तेमाल करें. ViewModel
ऑब्जेक्ट में, डेटा टाइप कोLiveData
में बदलें. टाइपLiveData
का रीड ओनली डेटा दिखाने के लिए, बैकिंग प्रॉपर्टी का इस्तेमाल करें.
दूसरा सवाल
अगर यूज़र इंटरफ़ेस (यूआई) कंट्रोलर, इनमें से किसी स्थिति में है, तो LiveData
यूज़र इंटरफ़ेस (यूआई) कंट्रोलर (जैसे कि फ़्रैगमेंट) अपडेट करता है?
- फिर से शुरू किया गया
- बैकग्राउंड में
- रोका गया है
- बंद किया गया
तीसरा सवाल
LiveData
ऑब्ज़र्वर पैटर्न में, निगरानी करने लायक आइटम (और क्या देखा जाता है) क्या होता है?
- ऑब्ज़र्वर का तरीका
LiveData
ऑब्जेक्ट में डेटा- यूज़र इंटरफ़ेस (यूआई) कंट्रोलर
ViewModel
ऑब्जेक्ट
अगला लेसन शुरू करें:
इस कोर्स में दिए गए दूसरे कोडलैब के लिंक के लिए, Android Kotlin की बुनियादी बातें कोडलैब का लैंडिंग पेज देखें.