Android Kotlin Fundamentals 07.5: RecyclerView में हेडर

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

परिचय

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

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

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

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

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

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

  • इस सीरीज़ के पिछले कोडलैब में दिए गए TrackMySleepQuality ऐप्लिकेशन का इस्तेमाल करें.
  • RecyclerView में दिखाई गई नींद की रातों के ऊपर, स्क्रीन की पूरी चौड़ाई में एक हेडर जोड़ें.

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

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

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

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

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

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

हेडर जोड़ने के दो तरीके

RecyclerView में, सूची के हर आइटम का इंडेक्स नंबर 0 से शुरू होता है. उदाहरण के लिए:

[Actual Data] -> [Adapter Views]

[0: SleepNight] -> [0: SleepNight]

[1: SleepNight] -> [1: SleepNight]

[2: SleepNight] -> [2: SleepNight]

किसी सूची में हेडर जोड़ने का एक तरीका यह है कि आप अपने अडैप्टर में बदलाव करें, ताकि वह किसी दूसरे ViewHolder का इस्तेमाल कर सके. इसके लिए, उन इंडेक्स की जांच करें जहां आपको हेडर दिखाना है. Adapter, हेडर को ट्रैक करने के लिए ज़िम्मेदार होगा. उदाहरण के लिए, टेबल में सबसे ऊपर हेडर दिखाने के लिए, आपको इंडेक्स किए गए आइटम को लेआउट करते समय, हेडर के लिए अलग ViewHolder वैल्यू दिखानी होगी. इसके बाद, अन्य सभी आइटम को हेडर ऑफ़सेट के साथ मैप किया जाएगा. जैसा कि यहां दिखाया गया है.

[Actual Data] -> [Adapter Views]

[0: Header]

[0: SleepNight] -> [1: SleepNight]

[1: SleepNight] -> [2: SleepNight]

[2: SleepNight] -> [3: SleepNight.

हेडर जोड़ने का दूसरा तरीका यह है कि अपनी डेटा ग्रिड के लिए, बैकअप के तौर पर इस्तेमाल किए जा रहे डेटासेट में बदलाव करें. दिखाया जाने वाला सारा डेटा सूची में सेव होता है. इसलिए, हेडर दिखाने के लिए सूची में आइटम शामिल किए जा सकते हैं. इसे समझना थोड़ा आसान है. हालांकि, इसके लिए आपको यह सोचना होगा कि ऑब्जेक्ट कैसे डिज़ाइन किए जाएं, ताकि अलग-अलग आइटम टाइप को एक ही सूची में शामिल किया जा सके. इस तरीके से लागू करने पर, अडैप्टर को पास किए गए आइटम दिखेंगे. इसलिए, पोज़िशन 0 पर मौजूद आइटम हेडर है और पोज़िशन 1 पर मौजूद आइटम SleepNight है. यह सीधे तौर पर स्क्रीन पर मौजूद कॉन्टेंट से मैप होता है.

[Actual Data] -> [Adapter Views]

[0: Header] -> [0: Header]

[1: SleepNight] -> [1: SleepNight]

[2: SleepNight] -> [2: SleepNight]

[3: SleepNight] -> [3: SleepNight]

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

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

पहला चरण: DataItem क्लास बनाना

आइटम के टाइप को अलग करने और अडैप्टर को सिर्फ़ "आइटम" से डील करने की अनुमति देने के लिए, एक डेटा होल्डर क्लास बनाई जा सकती है. यह क्लास, SleepNight या Header को दिखाती है. इसके बाद, आपका डेटासेट, डेटा होल्डर आइटम की सूची बन जाएगा.

GitHub से स्टार्टर ऐप्लिकेशन डाउनलोड किया जा सकता है. इसके अलावा, पिछले कोडलैब में बनाए गए SleepTracker ऐप्लिकेशन का इस्तेमाल जारी रखा जा सकता है.

  1. GitHub से RecyclerViewHeaders-Starter कोड डाउनलोड करें. RecyclerViewHeaders-Starter डायरेक्ट्री में, SleepTracker ऐप्लिकेशन का स्टार्टर वर्शन मौजूद है. यह कोडलैब के लिए ज़रूरी है. अगर आपको पसंद है, तो पिछले कोडलैब में बनाए गए ऐप्लिकेशन पर भी काम जारी रखा जा सकता है.
  2. SleepNightAdapter.kt खोलें.
  3. SleepNightListener क्लास के नीचे, सबसे ऊपर लेवल पर, sealed क्लास को DataItem के तौर पर तय करें. यह क्लास, डेटा के किसी आइटम को दिखाती है.

    sealed क्लास, क्लोज़्ड टाइप को तय करती है. इसका मतलब है कि DataItem की सभी सबक्लास को इस फ़ाइल में तय किया जाना चाहिए. इस वजह से, कंपाइलर को सबक्लास की संख्या के बारे में पता होता है. आपके कोड का कोई दूसरा हिस्सा, DataItem का नया टाइप तय नहीं कर सकता. इससे आपका अडैप्टर काम करना बंद कर सकता है.
sealed class DataItem {

 }
  1. DataItem क्लास के मुख्य हिस्से में, दो क्लास तय करें. ये क्लास, अलग-अलग तरह के डेटा आइटम को दिखाती हैं. पहला SleepNightItem है, जो SleepNight के चारों ओर एक रैपर है. इसलिए, यह sleepNight नाम की एक वैल्यू लेता है. इसे सील की गई क्लास का हिस्सा बनाने के लिए, इसे से बढ़ाएं.DataItem
data class SleepNightItem(val sleepNight: SleepNight): DataItem()
  1. दूसरी क्लास Header है, जिसका इस्तेमाल हेडर दिखाने के लिए किया जाता है. हेडर में कोई असल डेटा नहीं होता. इसलिए, इसे object के तौर पर तय किया जा सकता है. इसका मतलब है कि Header का सिर्फ़ एक इंस्टेंस होगा. इसे फिर से DataItem करें.
object Header: DataItem()
  1. क्लास लेवल पर DataItem के अंदर, id नाम की abstract Long प्रॉपर्टी तय करें. जब अडैप्टर, DiffUtil का इस्तेमाल करके यह तय करता है कि किसी आइटम में बदलाव हुआ है या नहीं और अगर हुआ है, तो किस तरह से, तब DiffUtil को हर आइटम का आईडी पता होना चाहिए.DiffItemCallback आपको एक गड़बड़ी दिखेगी, क्योंकि SleepNightItem और Header को ऐब्स्ट्रैक्ट प्रॉपर्टी id को बदलना होगा.
abstract val id: Long
  1. SleepNightItem में, nightId को वापस लाने के लिए id को बदलें.
override val id = sleepNight.nightId
  1. Header में, id को बदलें, ताकि Long.MIN_VALUE वैल्यू मिले. यह बहुत छोटी संख्या होती है. इसका मतलब है कि -2 की घात 63. इसलिए, यह कभी भी किसी मौजूदा nightId से मेल नहीं खाएगा.
override val id = Long.MIN_VALUE
  1. आपका पूरा किया गया कोड ऐसा दिखना चाहिए. साथ ही, आपका ऐप्लिकेशन बिना किसी गड़बड़ी के बनना चाहिए.
sealed class DataItem {
    abstract val id: Long
    data class SleepNightItem(val sleepNight: SleepNight): DataItem()      {
        override val id = sleepNight.nightId
    }

    object Header: DataItem() {
        override val id = Long.MIN_VALUE
    }
}

दूसरा चरण: हेडर के लिए ViewHolder बनाना

  1. header.xml नाम की नई लेआउट रिसॉर्स फ़ाइल में, हेडर के लिए लेआउट बनाएं. इसमें TextView दिखता है. इसमें कुछ भी दिलचस्प नहीं है, इसलिए यहां कोड दिया गया है.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Sleep Results"
    android:padding="8dp" />
  1. "Sleep Results" को स्ट्रिंग रिसॉर्स में बदलें और इसे header_text नाम दें.
<string name="header_text">Sleep Results</string>
  1. SleepNightAdapter.kt में, SleepNightAdapter के अंदर, ViewHolder क्लास के ऊपर, एक नई TextViewHolder क्लास बनाएं. यह क्लास, textview.xml लेआउट को बड़ा करती है और TextViewHolder इंस्टेंस दिखाती है. आपने यह काम पहले भी किया है. इसलिए, यहां कोड दिया गया है. आपको View और R इंपोर्ट करना होगा:
    class TextViewHolder(view: View): RecyclerView.ViewHolder(view) {
        companion object {
            fun from(parent: ViewGroup): TextViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val view = layoutInflater.inflate(R.layout.header, parent, false)
                return TextViewHolder(view)
            }
        }
    }

तीसरा चरण: SleepNightAdapter को अपडेट करना

इसके बाद, आपको SleepNightAdapter के बारे में एलान अपडेट करना होगा. इसे सिर्फ़ एक तरह के ViewHolder का इस्तेमाल करने के बजाय, किसी भी तरह के व्यू होल्डर का इस्तेमाल करने की सुविधा देनी होगी.

आइटम के टाइप तय करना

  1. SleepNightAdapter.kt में, सबसे ऊपर के लेवल पर, import स्टेटमेंट के नीचे और SleepNightAdapter के ऊपर, व्यू टाइप के लिए दो कॉन्स्टेंट तय करें.

    RecyclerView को हर आइटम के व्यू टाइप में अंतर करना होगा, ताकि वह उसे सही व्यू होल्डर असाइन कर सके.
    private val ITEM_VIEW_TYPE_HEADER = 0
    private val ITEM_VIEW_TYPE_ITEM = 1
  1. SleepNightAdapter के अंदर, getItemViewType() को बदलने के लिए एक फ़ंक्शन बनाएं. इससे मौजूदा आइटम के टाइप के आधार पर, सही हेडर या आइटम कॉन्स्टेंट दिखेगा.
override fun getItemViewType(position: Int): Int {
        return when (getItem(position)) {
            is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
            is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
        }
    }

SleepNightAdapter की परिभाषा अपडेट करें

  1. SleepNightAdapter की परिभाषा में, ListAdapter के पहले आर्ग्युमेंट को SleepNight से DataItem पर अपडेट करें.
  2. SleepNightAdapter की परिभाषा में, ListAdapter के दूसरे सामान्य तर्क को SleepNightAdapter.ViewHolder से बदलकर RecyclerView.ViewHolder करें. आपको ज़रूरी अपडेट के लिए कुछ गड़बड़ियां दिखेंगी. साथ ही, आपकी क्लास का हेडर इस तरह दिखना चाहिए.
class SleepNightAdapter(val clickListener: SleepNightListener):
       ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()) {

onCreateViewHolder() अपडेट करना

  1. onCreateViewHolder() के हस्ताक्षर को बदलकर RecyclerView.ViewHolder करें.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
  1. onCreateViewHolder() तरीके को लागू करने की सुविधा को बड़ा करें, ताकि हर आइटम टाइप के लिए सही व्यू होल्डर की जांच की जा सके और उसे वापस किया जा सके. अपडेट किया गया आपका तरीका, नीचे दिए गए कोड की तरह दिखना चाहिए.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ITEM_VIEW_TYPE_HEADER -> TextViewHolder.from(parent)
            ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
            else -> throw ClassCastException("Unknown viewType ${viewType}")
        }
    }

onBindViewHolder() अपडेट करना

  1. onBindViewHolder() के पैरामीटर टाइप को ViewHolder से बदलकर RecyclerView.ViewHolder करें.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
  1. सिर्फ़ ViewHolder होने पर, व्यू होल्डर को डेटा असाइन करने के लिए कोई शर्त जोड़ें.
        when (holder) {
            is ViewHolder -> {...}
  1. getItem() से मिले ऑब्जेक्ट टाइप को DataItem.SleepNightItem में बदलता है. आपका पूरा किया गया onBindViewHolder() फ़ंक्शन ऐसा दिखना चाहिए.
  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewHolder -> {
                val nightItem = getItem(position) as DataItem.SleepNightItem
                holder.bind(nightItem.sleepNight, clickListener)
            }
        }
    }

diffUtil कॉलबैक अपडेट करना

  1. SleepNightDiffCallback में दिए गए तरीकों को बदलकर, SleepNight के बजाय अपनी नई DataItem क्लास का इस्तेमाल करें. नीचे दिए गए कोड में दिखाए गए तरीके से, लिंट की चेतावनी को छिपाएं.
class SleepNightDiffCallback : DiffUtil.ItemCallback<DataItem>() {
    override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem.id == newItem.id
    }
    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem == newItem
    }
}

हेडर जोड़ना और सबमिट करना

  1. SleepNightAdapter के अंदर, onCreateViewHolder() के नीचे, addHeaderAndSubmitList() फ़ंक्शन को यहां दिखाए गए तरीके से तय करें. यह फ़ंक्शन, SleepNight की सूची लेता है. अपनी सूची सबमिट करने के लिए, ListAdapter की ओर से उपलब्ध कराए गए submitList() का इस्तेमाल करने के बजाय, आपको इस फ़ंक्शन का इस्तेमाल करके हेडर जोड़ना होगा. इसके बाद, सूची सबमिट करनी होगी.
fun addHeaderAndSubmitList(list: List<SleepNight>?) {}
  1. addHeaderAndSubmitList() के अंदर, अगर पास की गई सूची null है, तो सिर्फ़ हेडर दिखाएं. ऐसा न होने पर, हेडर को सूची के सबसे ऊपर जोड़ें. इसके बाद, सूची सबमिट करें.
val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
submitList(items)
  1. SleepTrackerFragment.kt खोलें और submitList() को addHeaderAndSubmitList() में बदलें.
  1. अपने ऐप्लिकेशन को चलाएं और देखें कि नींद से जुड़े आइटम की सूची में, आपका हेडर पहले आइटम के तौर पर कैसे दिखता है.

इस ऐप्लिकेशन के लिए, दो समस्याएं ठीक करनी होंगी. इनमें से एक समस्या दिख रही है और दूसरी नहीं दिख रही है.

  • हेडर, सबसे ऊपर बाएं कोने में दिखता है और इसे आसानी से पहचाना नहीं जा सकता.
  • एक हेडर वाली छोटी सूची के लिए, इससे ज़्यादा फ़र्क़ नहीं पड़ता. हालांकि, आपको यूज़र इंटरफ़ेस (यूआई) थ्रेड पर addHeaderAndSubmitList() में सूची में बदलाव नहीं करना चाहिए. मान लीजिए कि आपके पास सैकड़ों आइटम वाली कोई सूची है, जिसमें कई हेडर हैं. साथ ही, यह तय करने के लिए लॉजिक है कि आइटम कहां डालने हैं. यह काम एक को-रूटीन में होना चाहिए.

कोरूटीन का इस्तेमाल करने के लिए, addHeaderAndSubmitList() को बदलें:

  1. SleepNightAdapter क्लास में सबसे ऊपर, Dispatchers.Default की मदद से CoroutineScope को तय करें.
private val adapterScope = CoroutineScope(Dispatchers.Default)
  1. addHeaderAndSubmitList() में, सूची में बदलाव करने के लिए adapterScope में एक कोरूटीन लॉन्च करें. इसके बाद, सूची सबमिट करने के लिए Dispatchers.Main कॉन्टेक्स्ट पर स्विच करें. इसे नीचे दिए गए कोड में दिखाया गया है.
 fun addHeaderAndSubmitList(list: List<SleepNight>?) {
        adapterScope.launch {
            val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
            withContext(Dispatchers.Main) {
                submitList(items)
            }
        }
    }
  1. आपका कोड बिल्ड और रन होना चाहिए. साथ ही, आपको कोई अंतर नहीं दिखेगा.

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

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

  1. SleepTrackerFragment.kt खोलें.
  2. onCreateView() के आखिर में, manager को तय करने वाला कोड ढूंढें.
val manager = GridLayoutManager(activity, 3)
  1. नीचे दिए गए तरीके से, manager के नीचे manager.spanSizeLookup को तय करें. आपको object बनाना होगा, क्योंकि setSpanSizeLookup में लैम्डा फ़ंक्शन का इस्तेमाल नहीं किया जा सकता. Kotlin में object बनाने के लिए, object : classname टाइप करें. इस मामले में, GridLayoutManager.SpanSizeLookup.
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
}
  1. कंस्ट्रक्टर को कॉल करने के लिए, आपको कंपाइलर से जुड़ी गड़बड़ी का मैसेज मिल सकता है. अगर ऐसा होता है, तो कंस्ट्रक्टर कॉल लागू करने के लिए, Option+Enter (Mac) या Alt+Enter (Windows) का इस्तेमाल करके इंटेंशन मेन्यू खोलें.
  1. इसके बाद, आपको object पर गड़बड़ी का मैसेज मिलेगा. इसमें बताया जाएगा कि आपको तरीकों को बदलना होगा. कर्सर को object पर रखें. इसके बाद, इंटेंशन मेन्यू खोलने के लिए Option+Enter (Mac) या Alt+Enter (Windows) दबाएं. फिर, getSpanSize() तरीके को बदलें.
  1. getSpanSize() के मुख्य हिस्से में, हर पोज़िशन के लिए सही स्पैन साइज़ दिखाएं. पोजीशन 0 का स्पैन साइज़ 3 है और बाकी पोजीशन का स्पैन साइज़ 1 है. आपका पूरा कोड, यहां दिए गए कोड की तरह दिखना चाहिए:
    manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int) =  when (position) {
                0 -> 3
                else -> 1
            }
        }
  1. हेडर को बेहतर बनाने के लिए, header.xml खोलें और इस कोड को लेआउट फ़ाइल header.xml में जोड़ें.
android:textColor="@color/white_text_color"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorAccent"
  1. अपना ऐप्लिकेशन चलाएं. यह नीचे दिए गए स्क्रीनशॉट की तरह दिखना चाहिए.

बधाई हो! प्रक्रिया पूरी हो गई है.

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

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

हेडर जोड़ने के लिए, यह तरीका अपनाएं:

  • अपनी सूची में मौजूद डेटा को छोटा करने के लिए, DataItem बनाएं. इसमें हेडर या डेटा शामिल किया जा सकता है.
  • अडैप्टर में हेडर के लिए लेआउट वाला व्यू होल्डर बनाएं.
  • किसी भी तरह के RecyclerView.ViewHolder का इस्तेमाल करने के लिए, अडैप्टर और उसके तरीकों को अपडेट करें.
  • onCreateViewHolder() में, डेटा आइटम के लिए सही टाइप का व्यू होल्डर दिखाएं.
  • DataItem क्लास के साथ काम करने के लिए, SleepNightDiffCallback को अपडेट करें.
  • एक addHeaderAndSubmitList() फ़ंक्शन बनाएं, जो डेटासेट में हेडर जोड़ने के लिए कोरूटीन का इस्तेमाल करता हो. इसके बाद, submitList() को कॉल करता हो.
  • सिर्फ़ हेडर को तीन स्पैन की चौड़ाई देने के लिए, GridLayoutManager.SpanSizeLookup() लागू करें.

Udacity का कोर्स:

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

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

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

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

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

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

पहला सवाल

ViewHolder के बारे में इनमें से कौनसी बात सही है?

▢ अडैप्टर, हेडर और अलग-अलग तरह के डेटा को सेव करने के लिए, कई ViewHolder क्लास का इस्तेमाल कर सकता है.

▢ डेटा के लिए सिर्फ़ एक व्यू होल्डर और हेडर के लिए सिर्फ़ एक व्यू होल्डर हो सकता है.

RecyclerView में कई तरह के हेडर इस्तेमाल किए जा सकते हैं, लेकिन डेटा एक जैसा होना चाहिए.

▢ हेडर जोड़ते समय, सही जगह पर हेडर डालने के लिए RecyclerView का इस्तेमाल किया जाता है.

दूसरा सवाल

आपको RecyclerView के साथ कोरूटीन का इस्तेमाल कब करना चाहिए? सभी सही जवाब चुनें.

▢ कभी नहीं. RecyclerView एक यूज़र इंटरफ़ेस (यूआई) एलिमेंट है और इसमें को-रूटीन का इस्तेमाल नहीं किया जाना चाहिए.

▢ लंबे समय तक चलने वाले ऐसे टास्क के लिए कोरूटीन का इस्तेमाल करें जिनसे यूज़र इंटरफ़ेस (यूआई) धीमा हो सकता है.

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

▢ मुख्य थ्रेड को ब्लॉक होने से बचाने के लिए, निलंबन फ़ंक्शन के साथ कोरूटीन का इस्तेमाल करें.

तीसरा सवाल

एक से ज़्यादा ViewHolder का इस्तेमाल करते समय, इनमें से कौनसा काम नहीं करना पड़ता?

ViewHolder में, ज़रूरत के मुताबिक लेआउट फ़ाइलें उपलब्ध कराएं.

onCreateViewHolder() में, डेटा आइटम के लिए सही टाइप का व्यू होल्डर दिखाएं.

onBindViewHolder() में, डेटा को सिर्फ़ तब बाइंड करें, जब व्यू होल्डर, डेटा आइटम के लिए सही टाइप का व्यू होल्डर हो.

▢ किसी भी RecyclerView.ViewHolder को स्वीकार करने के लिए, अडैप्टर क्लास के सिग्नेचर को सामान्य बनाएं.

अगला सबक शुरू करें: 8.1 इंटरनेट से डेटा पाना

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