Android Kotlin Fundamentals 07.4: RecyclerView आइटम के साथ इंटरैक्ट करना

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

परिचय

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

इस कोडलैब में, आपको अपने RecyclerView में इंटरैक्शन जोड़ने का तरीका बताया जाएगा. इसके लिए, कोडलैब की पिछली सीरीज़ में दिए गए स्लीप-ट्रैकर ऐप्लिकेशन के एक्सटेंडेड वर्शन का इस्तेमाल किया जाएगा.

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

  • ऐक्टिविटी, फ़्रैगमेंट, और व्यू का इस्तेमाल करके बुनियादी यूज़र इंटरफ़ेस बनाना.
  • फ़्रैगमेंट के बीच नेविगेट करना और फ़्रैगमेंट के बीच डेटा पास करने के लिए, safeArgs का इस्तेमाल करना.
  • मॉडल, मॉडल फ़ैक्ट्री, ट्रांसफ़ॉर्मेशन, और LiveData और उनके ऑब्ज़र्वर देखें.
  • Room डेटाबेस बनाने, डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) बनाने, और इकाइयों को तय करने का तरीका.
  • डेटाबेस और अन्य लंबे समय तक चलने वाले टास्क के लिए, कोराउटीन का इस्तेमाल कैसे करें.
  • Adapter, ViewHolder, और आइटम लेआउट के साथ बुनियादी RecyclerView को लागू करने का तरीका.
  • RecyclerView के लिए डेटा बाइंडिंग लागू करने का तरीका.
  • डेटा को बदलने के लिए, बाइंडिंग अडैप्टर बनाने और उनका इस्तेमाल करने का तरीका.
  • GridLayoutManager का इस्तेमाल कैसे करें.

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

  • RecyclerView में मौजूद आइटम को क्लिक करने लायक बनाने का तरीका. किसी आइटम पर क्लिक करने पर, ज़्यादा जानकारी वाले व्यू पर जाने के लिए, क्लिक लिसनर लागू करें.

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

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

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

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

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

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

पहला चरण: स्टार्टर ऐप्लिकेशन डाउनलोड करना

  1. GitHub से RecyclerViewClickHandler-Starter कोड डाउनलोड करें और Android Studio में प्रोजेक्ट खोलें.
  2. नींद को ट्रैक करने वाला शुरुआती ऐप्लिकेशन बनाएं और उसे चलाएं.

[ज़रूरी नहीं] अगर आपको पिछले कोडलैब के ऐप्लिकेशन का इस्तेमाल करना है, तो उसे अपडेट करें

अगर आपको इस कोडलैब के लिए, GitHub में दिए गए स्टार्टर ऐप्लिकेशन का इस्तेमाल करना है, तो अगले चरण पर जाएं.

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

  1. अगर आपको अपने मौजूदा ऐप्लिकेशन का इस्तेमाल जारी रखना है, तो GitHub से RecyclerViewClickHandler-Starter कोड पाएं, ताकि फ़ाइलों को कॉपी किया जा सके.
  2. sleepdetail पैकेज में मौजूद सभी फ़ाइलें कॉपी करें.
  3. layout फ़ोल्डर में, fragment_sleep_detail.xml फ़ाइल को कॉपी करें.
  4. navigation.xml के अपडेट किए गए कॉन्टेंट को कॉपी करें. इससे sleep_detail_fragment के लिए नेविगेशन जोड़ा जाता है.
  5. database पैकेज में, SleepDatabaseDao में, नया getNightWithId() तरीका जोड़ें:
/**
 * Selects and returns the night with given nightId.
*/
@Query("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
fun getNightWithId(key: Long): LiveData<SleepNight>
  1. res/values/strings में, यह स्ट्रिंग रिसॉर्स जोड़ें:
<string name="close">Close</string>
  1. डेटा बाइंडिंग को अपडेट करने के लिए, अपने ऐप्लिकेशन को क्लीन करें और फिर से बनाएं.

दूसरा चरण: नींद की जानकारी वाली स्क्रीन के लिए कोड की जांच करना

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

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

  2. sleepdetail पैकेज में, SleepDetailViewModel का कोड खोलें और उसकी जांच करें. यह व्यू मॉडल, कंस्ट्रक्टर में SleepNight और DAO के लिए कुंजी लेता है.

    क्लास के मुख्य हिस्से में, दी गई कुंजी के लिए SleepNight को पाने का कोड होता है. साथ ही, navigateToSleepTracker वैरिएबल होता है, ताकि बंद करें बटन दबाने पर, वापस SleepTrackerFragment पर नेविगेट किया जा सके.

    getNightWithId() फ़ंक्शन, LiveData<SleepNight> दिखाता है. इसे SleepDatabaseDao (database पैकेज में) में तय किया गया है.

  3. sleepdetail पैकेज में, SleepDetailFragment का कोड खोलें और उसकी जांच करें. डेटा बाइंडिंग, व्यू मॉडल, और नेविगेशन के लिए ऑब्ज़र्वर के सेटअप पर ध्यान दें.

  4. sleepdetail पैकेज में, SleepDetailViewModelFactory का कोड खोलें और उसकी जांच करें.

  5. लेआउट फ़ोल्डर में, fragment_sleep_detail.xml की जांच करें. व्यू मॉडल से हर व्यू में डेटा दिखाने के लिए, <data> टैग में तय किए गए sleepDetailViewModel वैरिएबल पर ध्यान दें.

    लेआउट में एक ConstraintLayout होता है. इसमें नींद की क्वालिटी के लिए ImageView, क्वालिटी रेटिंग के लिए TextView, नींद की अवधि के लिए TextView, और ज़्यादा जानकारी वाले फ़्रैगमेंट को बंद करने के लिए Button होता है.

  6. navigation.xml फ़ाइल खोलें. sleep_tracker_fragment के लिए, sleep_detail_fragment के लिए नई कार्रवाई देखें.

    नई कार्रवाई, action_sleep_tracker_fragment_to_sleepDetailFragment, स्लीप ट्रैकर फ़्रैगमेंट से जानकारी वाली स्क्रीन पर नेविगेशन है.

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

क्लिक पाना और उन्हें हैंडल करना, दो हिस्सों में बंटा हुआ काम है: पहला, आपको क्लिक को सुनना और पाना होगा. साथ ही, यह तय करना होगा कि किस आइटम पर क्लिक किया गया है. इसके बाद, आपको क्लिक पर कोई कार्रवाई करनी होगी.

इसलिए, इस ऐप्लिकेशन के लिए क्लिक लिसनर जोड़ने की सबसे अच्छी जगह कौनसी है?

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

ViewHolder में क्लिक इवेंट को सुना जा सकता है. हालांकि, आम तौर पर क्लिक इवेंट को हैंडल करने के लिए यह सही जगह नहीं होती. इसलिए, क्लिक को मैनेज करने के लिए सबसे सही जगह कौनसी है?

  • Adapter व्यू में डेटा आइटम दिखाता है, इसलिए अडैप्टर में क्लिक हैंडल किए जा सकते हैं. हालांकि, अडैप्टर का काम डेटा को डिसप्ले के लिए अडैप्ट करना है, न कि ऐप्लिकेशन के लॉजिक को मैनेज करना.
  • आम तौर पर, आपको ViewModel में क्लिक हैंडल करने चाहिए, क्योंकि ViewModel के पास डेटा और लॉजिक का ऐक्सेस होता है. इससे यह तय किया जा सकता है कि क्लिक के जवाब में क्या होना चाहिए.

पहला चरण: क्लिक लिसनर बनाएं और उसे आइटम लेआउट से ट्रिगर करें

  1. sleeptracker फ़ोल्डर में, SleepNightAdapter.kt खोलें.
  2. फ़ाइल के आखिर में, सबसे ऊपर लेवल पर, नई लिसनर क्लास SleepNightListener बनाएं.
class SleepNightListener() {
    
}
  1. SleepNightListener क्लास में, onClick() फ़ंक्शन जोड़ें. जब सूची में मौजूद किसी आइटम को दिखाने वाले व्यू पर क्लिक किया जाता है, तो व्यू इस onClick() फ़ंक्शन को कॉल करता है. (बाद में, आपको इस फ़ंक्शन के लिए व्यू की android:onClick प्रॉपर्टी सेट करनी होगी.)
class SleepNightListener() {
    fun onClick() = 
}
  1. onClick() में night टाइप का फ़ंक्शन आर्ग्युमेंट SleepNight जोड़ें. व्यू को पता होता है कि वह कौनसे आइटम को दिखा रहा है. क्लिक को हैंडल करने के लिए, इस जानकारी को पास करना ज़रूरी होता है.
class SleepNightListener() {
    fun onClick(night: SleepNight) = 
}
  1. onClick() के काम करने का तरीका तय करने के लिए, SleepNightListener के कंस्ट्रक्टर में clickListener कॉलबैक दें और उसे onClick() को असाइन करें.

    क्लिक को हैंडल करने वाले लैम्डा को नाम देने से, clickListener , इसे ट्रैक करने में मदद मिलती है, क्योंकि इसे क्लास के बीच पास किया जाता है. डेटाबेस से डेटा ऐक्सेस करने के लिए, clickListener कॉलबैक को सिर्फ़ night.nightId की ज़रूरत होती है. आपकी पूरी की गई SleepNightListener क्लास, नीचे दिए गए कोड की तरह दिखनी चाहिए.
class SleepNightListener(val clickListener: (sleepId: Long) -> Unit) {
   fun onClick(night: SleepNight) = clickListener(night.nightId)
}
  1. list_item_sleep_night.xml. खोलें.
  2. data ब्लॉक में, एक नया वैरिएबल जोड़ें, ताकि डेटा बाइंडिंग के ज़रिए SleepNightListener क्लास उपलब्ध कराई जा सके. नई <variable> को name का clickListener. दें. type को क्लास com.example.android.trackmysleepquality.sleeptracker.SleepNightListener के पूरी तरह क्वालिफ़ाइड नाम पर सेट करें. इसे नीचे दिखाया गया है. अब इस लेआउट से, SleepNightListener में onClick() फ़ंक्शन को ऐक्सेस किया जा सकता है.
<variable
            name="clickListener"
            type="com.example.android.trackmysleepquality.sleeptracker.SleepNightListener" />
  1. इस सूची आइटम के किसी भी हिस्से पर होने वाले क्लिक को सुनने के लिए, ConstraintLayout में android:onClick एट्रिब्यूट जोड़ें.

    नीचे दिखाए गए तरीके से, डेटा बाइंडिंग लैम्डा का इस्तेमाल करके एट्रिब्यूट को clickListener:onClick(sleep) पर सेट करें:
android:onClick="@{() -> clickListener.onClick(sleep)}"

दूसरा चरण: क्लिक लिसनर को व्यू होल्डर और बाइंडिंग ऑब्जेक्ट पर पास करना

  1. SleepNightAdapter.kt खोलें.
  2. val clickListener: SleepNightListener पाने के लिए, SleepNightAdapter क्लास के कंस्ट्रक्टर में बदलाव करें. जब अडैप्टर ViewHolder को बाइंड करता है, तब उसे यह क्लिक लिसनर देना होगा.
class SleepNightAdapter(val clickListener: SleepNightListener):
       ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. onBindViewHolder() में, कॉल को holder.bind() पर अपडेट करें, ताकि क्लिक लिसनर को ViewHolder पर भी पास किया जा सके. आपको कंपाइलर से जुड़ी गड़बड़ी मिलेगी, क्योंकि आपने फ़ंक्शन कॉल में एक पैरामीटर जोड़ा है.
holder.bind(getItem(position)!!, clickListener)
  1. bind() में clickListener पैरामीटर जोड़ें. इसके लिए, कर्सर को गड़बड़ी पर रखें. इसके बाद, नीचे दिए गए स्क्रीनशॉट में दिखाए गए तरीके से , गड़बड़ी पर Alt+Enter (Windows) या Option+Enter (Mac) दबाएं.

  1. ViewHolder क्लास में, bind() फ़ंक्शन के अंदर, binding ऑब्जेक्ट को क्लिक लिसनर असाइन करें. आपको गड़बड़ी दिख रही है, क्योंकि आपको बाइंडिंग ऑब्जेक्ट को अपडेट करना है.
binding.clickListener = clickListener
  1. डेटा बाइंडिंग को अपडेट करने के लिए, अपने प्रोजेक्ट को क्लीन करें और फिर से बनाएं. (आपको कैश मेमोरी भी मिटानी पड़ सकती है.) इसलिए, आपने अडैप्टर कंस्ट्रक्टर से क्लिक लिसनर लिया है और उसे व्यू होल्डर और बाइंडिंग ऑब्जेक्ट में पास किया है.

तीसरा चरण: किसी आइटम पर टैप करने पर, एक सूचना दिखाना

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

  1. SleepTrackerFragment.kt खोलें.
  2. onCreateView() में, adapter वैरिएबल ढूंढें. ध्यान दें कि अब इसमें गड़बड़ी दिख रही है, क्योंकि अब इसे क्लिक लिसनर पैरामीटर की ज़रूरत है.
  3. SleepNightAdapter में लैंबडा पास करके, क्लिक लिसनर को डिफ़ाइन करें. यह सामान्य लैम्डा, नीचे दिखाए गए तरीके से nightId दिखाने वाला एक सूचना मैसेज दिखाता है. आपको Toast इंपोर्ट करना होगा. अपडेट की गई पूरी परिभाषा यहां दी गई है.
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
   Toast.makeText(context, "${nightId}", Toast.LENGTH_LONG).show()
})
  1. ऐप्लिकेशन चलाएं, आइटम पर टैप करें, और पुष्टि करें कि वे सही nightId के साथ एक सूचना दिखा रहे हैं. आइटम की nightId वैल्यू बढ़ रही है. साथ ही, ऐप्लिकेशन में सबसे हाल की रात की जानकारी सबसे पहले दिखती है. इसलिए, सबसे कम nightId वैल्यू वाला आइटम, सूची में सबसे नीचे है.

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

पहला चरण: क्लिक करने पर नेविगेट करना

इस चरण में, सिर्फ़ एक सूचना दिखाने के बजाय, SleepTrackerFragment के onCreateView() में क्लिक लिसनर लैम्डा को बदलें, ताकि nightId को SleepTrackerViewModel पर भेजा जा सके और SleepDetailFragment पर नेविगेशन ट्रिगर किया जा सके.

क्लिक हैंडलर फ़ंक्शन को इस तरह से तय करें:

  1. SleepTrackerViewModel.kt खोलें.
  2. SleepTrackerViewModel के अंदर, आखिर में onSleepNightClicked()click handler फ़ंक्शन तय करें.
fun onSleepNightClicked(id: Long) {

}
  1. onSleepNightClicked() के अंदर, क्लिक किए गए स्लीप नाइट के id को _navigateToSleepDetail पर सेट करके, नेविगेशन को ट्रिगर करें.
fun onSleepNightClicked(id: Long) {
   _navigateToSleepDetail.value = id
}
  1. _navigateToSleepDetail लागू करें. नेविगेशन की स्थिति के लिए, पहले की तरह private MutableLiveData तय करें. इसके साथ ही, सार्वजनिक तौर पर उपलब्ध val भी होना चाहिए.
private val _navigateToSleepDetail = MutableLiveData<Long>()
val navigateToSleepDetail
   get() = _navigateToSleepDetail
  1. ऐप्लिकेशन के नेविगेट करने के बाद कॉल करने का तरीका तय करें. इसे onSleepDetailNavigated() नाम दें और इसकी वैल्यू को null पर सेट करें.
fun onSleepDetailNavigated() {
    _navigateToSleepDetail.value = null
}

क्लिक हैंडलर को कॉल करने के लिए, यह कोड जोड़ें:

  1. SleepTrackerFragment.kt खोलें और उस कोड तक नीचे की ओर स्क्रोल करें जो अडैप्टर बनाता है और SleepNightListener को टोस्ट दिखाने के लिए तय करता है.
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
   Toast.makeText(context, "${nightId}", Toast.LENGTH_LONG).show()
})
  1. किसी आइटम पर टैप करने पर, sleepTrackerViewModel में क्लिक हैंडलर onSleepNighClicked() को कॉल करने के लिए, नीचे दिया गया कोड, सूचना के नीचे जोड़ें. nightId पास करें, ताकि व्यू मॉडल को पता चल सके कि किस रात की नींद का डेटा पाना है. इस वजह से, आपको गड़बड़ी का मैसेज मिलता है, क्योंकि आपने अब तक onSleepNightClicked() को तय नहीं किया है. आपके पास यह विकल्प होता है कि आप सूचना को रखें, उसे टिप्पणी के तौर पर इस्तेमाल करें या मिटा दें.
sleepTrackerViewModel.onSleepNightClicked(nightId)

क्लिक ट्रैक करने के लिए, यह कोड जोड़ें:

  1. SleepTrackerFragment.kt खोलें.
  2. onCreateView() में, manager के एलान से ठीक ऊपर, नया navigateToSleepDetail LiveData देखने के लिए कोड जोड़ें. जब navigateToSleepDetail बदलता है, तो SleepDetailFragment पर जाएं. इसके बाद, night पास करें और फिर onSleepDetailNavigated() को कॉल करें. आपने पिछले कोडलैब में यह काम किया था. इसलिए, यहां कोड दिया गया है:
sleepTrackerViewModel.navigateToSleepDetail.observe(this, Observer { night ->
            night?.let {
              this.findNavController().navigate(
                        SleepTrackerFragmentDirections
                                .actionSleepTrackerFragmentToSleepDetailFragment(night))
               sleepTrackerViewModel.onSleepDetailNavigated()
            }
        })
  1. कोड चलाने के बाद, किसी आइटम पर क्लिक करें और ... ऐप्लिकेशन क्रैश हो जाता है.

बाइंडिंग अडैप्टर में शून्य वैल्यू मैनेज करना:

  1. ऐप्लिकेशन को डीबग मोड में फिर से चलाएं. किसी आइटम पर टैप करें और गड़बड़ियां दिखाने के लिए लॉग फ़िल्टर करें. इससे स्टैक ट्रेस दिखेगा. इसमें नीचे दी गई जानकारी भी शामिल होगी.
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter item

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

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

  1. BindingUtils.kt में, हर बाइंडिंग अडैप्टर के लिए, item आर्ग्युमेंट के टाइप को नल हो सकने वाले टाइप में बदलें. साथ ही, बॉडी को item?.let{...} से रैप करें. उदाहरण के लिए, sleepQualityString के लिए आपका अडैप्टर ऐसा दिखेगा. इसी तरह, अन्य अडैप्टर में भी बदलाव करें.
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight?) {
   item?.let {
       text = convertNumericQualityToString(item.sleepQuality, context.resources)
   }
}
  1. अपना ऐप्लिकेशन चलाएं. किसी आइटम पर टैप करें. इसके बाद, ज़्यादा जानकारी वाला व्यू खुल जाएगा.

Android Studio प्रोजेक्ट: RecyclerViewClickHandler.

RecyclerView में मौजूद आइटम को क्लिक करने लायक बनाने के लिए, ViewHolder में मौजूद सूची के आइटम में क्लिक लिसनर अटैच करें. इसके बाद, ViewModel में क्लिक हैंडल करें.

RecyclerView में मौजूद आइटम पर क्लिक करने पर कार्रवाई हो, इसके लिए आपको ये काम करने होंगे:

  • एक लिसनर क्लास बनाएं, जो lambda लेता है और उसे onClick() फ़ंक्शन को असाइन करता है.
class SleepNightListener(val clickListener: (sleepId: Long) -> Unit) {
   fun onClick(night: SleepNight) = clickListener(night.nightId)
}
  • व्यू पर क्लिक लिसनर सेट करें.
android:onClick="@{() -> clickListener.onClick(sleep)}"
  • क्लिक लिसनर को अडैप्टर कंस्ट्रक्टर, व्यू होल्डर में पास करें. इसके बाद, इसे बाइंडिंग ऑब्जेक्ट में जोड़ें.
class SleepNightAdapter(val clickListener: SleepNightListener):
       ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()
holder.bind(getItem(position)!!, clickListener)
binding.clickListener = clickListener
  • रीसाइक्लर व्यू दिखाने वाले फ़्रैगमेंट में, जहां अडैप्टर बनाया जाता है वहां अडैप्टर को लैंबडा पास करके, क्लिक लिसनर तय करें.
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
      sleepTrackerViewModel.onSleepNightClicked(nightId)
})
  • व्यू मॉडल में क्लिक हैंडलर लागू करें. सूची में मौजूद आइटम पर क्लिक करने पर, आम तौर पर यह नेविगेशन को जानकारी वाले फ़्रैगमेंट पर ट्रिगर करता है.

Udacity का कोर्स:

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

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

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

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

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

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

पहला सवाल

मान लें कि आपके ऐप्लिकेशन में एक RecyclerView है, जो खरीदारी की सूची में आइटम दिखाता है. आपका ऐप्लिकेशन, क्लिक-लिसनर क्लास भी तय करता है:

class ShoppingListItemListener(val clickListener: (itemId: Long) -> Unit) {
    fun onClick(cartItem: CartItem) = clickListener(cartItem.itemId)
}

डेटा बाइंडिंग के लिए, ShoppingListItemListener को कैसे उपलब्ध कराया जाता है? कोई एक चुनें.

▢ लेआउट फ़ाइल में, RecyclerView जोड़ें. यह RecyclerView, खरीदारी की सूची दिखाता है. इसके बाद, ShoppingListItemListener के लिए <data> वैरिएबल जोड़ें.

▢ लेआउट फ़ाइल में, शॉपिंग लिस्ट की किसी एक लाइन के लिए लेआउट तय करें. इसके बाद, ShoppingListItemListener के लिए <data> वैरिएबल जोड़ें.

ShoppingListItemListener क्लास में, डेटा बाइंडिंग की सुविधा चालू करने के लिए एक फ़ंक्शन जोड़ें:

fun onBinding (cartItem: CartItem) {dataBindingEnable(true)}

ShoppingListItemListener क्लास में, onClick() फ़ंक्शन के अंदर, डेटा बाइंडिंग चालू करने के लिए कॉल जोड़ें:

fun onClick(cartItem: CartItem) = { 
    clickListener(cartItem.itemId)
    dataBindingEnable(true)
}

दूसरा सवाल

RecyclerView एट्रिब्यूट को कहां जोड़ा जाता है, ताकि RecyclerView में मौजूद आइटम पर क्लिक करने पर प्रतिक्रिया मिल सके?android:onClick लागू होने वाले सभी विकल्पों को चुनें.

RecyclerView दिखाने वाली लेआउट फ़ाइल में, इसे <androidx.recyclerview.widget.RecyclerView> में जोड़ें

▢ इसे लाइन में मौजूद किसी आइटम की लेआउट फ़ाइल में जोड़ें. अगर आपको पूरे आइटम को क्लिक करने लायक बनाना है, तो उसे पैरंट व्यू में जोड़ें. इस पैरंट व्यू में, लाइन में मौजूद आइटम शामिल होते हैं.

▢ इसे लाइन में मौजूद किसी आइटम की लेआउट फ़ाइल में जोड़ें. अगर आपको आइटम में मौजूद किसी एक TextView को क्लिक करने लायक बनाना है, तो उसे <TextView> में जोड़ें.

▢ इसे हमेशा MainActivity के लिए लेआउट फ़ाइल में जोड़ें.

अगला लेसन शुरू करें: 7.5: RecyclerView में हेडर