यह कोडलैब, Android Kotlin Fundamentals कोर्स का हिस्सा है. अगर कोडलैब को क्रम से पूरा किया जाता है, तो आपको इस कोर्स से सबसे ज़्यादा फ़ायदा मिलेगा. कोर्स के सभी कोडलैब, Android Kotlin Fundamentals कोडलैब के लैंडिंग पेज पर दिए गए हैं.
परिचय
पिछले कोडलैब में, आपने TrackMySleepQuality ऐप्लिकेशन को अपडेट किया था, ताकि RecyclerView
में नींद की क्वालिटी के बारे में डेटा दिखाया जा सके. आपने अपना पहला RecyclerView
बनाते समय जो तकनीकें सीखी थीं वे ज़्यादातर RecyclerViews
के लिए काफ़ी हैं. ये RecyclerViews
, ज़्यादा बड़ी नहीं होती हैं और इनमें सामान्य सूचियां दिखती हैं. हालांकि, ऐसी कई तकनीकें हैं जिनकी मदद से, बड़ी सूचियों के लिए RecyclerView
को ज़्यादा असरदार बनाया जा सकता है. साथ ही, जटिल सूचियों और ग्रिड के लिए अपने कोड को बनाए रखना और उसे बढ़ाना आसान बनाया जा सकता है.
इस कोडलैब में, पिछले कोडलैब में बनाए गए स्लीप-ट्रैकर ऐप्लिकेशन का इस्तेमाल किया जाता है. आपको नींद से जुड़े डेटा की सूची को अपडेट करने का ज़्यादा असरदार तरीका पता चलता है. साथ ही, आपको RecyclerView
के साथ डेटा बाइंडिंग का इस्तेमाल करने का तरीका पता चलता है. (अगर आपके पास पिछले कोडलैब का ऐप्लिकेशन नहीं है, तो इस कोडलैब के लिए स्टार्टर कोड डाउनलोड किया जा सकता है.)
आपको पहले से क्या पता होना चाहिए
- ऐक्टिविटी, फ़्रैगमेंट, और व्यू का इस्तेमाल करके बुनियादी यूज़र इंटरफ़ेस बनाना.
- फ़्रैगमेंट के बीच नेविगेट करना और फ़्रैगमेंट के बीच डेटा पास करने के लिए,
safeArgs
का इस्तेमाल करना. - मॉडल, मॉडल फ़ैक्ट्री, ट्रांसफ़ॉर्मेशन, और
LiveData
और उनके ऑब्ज़र्वर देखें. Room
डेटाबेस बनाने, DAO बनाने, और इकाइयों को तय करने का तरीका.- डेटाबेस और अन्य लंबे समय तक चलने वाले टास्क के लिए, कोराउटीन का इस्तेमाल कैसे करें.
Adapter
,ViewHolder
, और आइटम लेआउट के साथ बुनियादीRecyclerView
को लागू करने का तरीका.
आपको क्या सीखने को मिलेगा
RecyclerView
की ओर से दिखाई गई सूची को असरदार तरीके से अपडेट करने के लिए,DiffUtil
का इस्तेमाल कैसे करें.RecyclerView
के साथ डेटा बाइंडिंग का इस्तेमाल करने का तरीका.- डेटा को बदलने के लिए, बाइंडिंग अडैप्टर का इस्तेमाल कैसे करें.
आपको क्या करना होगा
- इस सीरीज़ के पिछले कोडलैब में दिए गए TrackMySleepQuality ऐप्लिकेशन का इस्तेमाल करें.
DiffUtil
का इस्तेमाल करके सूची को आसानी से अपडेट करने के लिए,SleepNightAdapter
को अपडेट करें.- डेटा को बदलने के लिए, बाइंडिंग अडैप्टर का इस्तेमाल करके
RecyclerView
के लिए डेटा बाइंडिंग लागू करें.
नींद को ट्रैक करने वाले ऐप्लिकेशन में दो स्क्रीन होती हैं. इन्हें फ़्रैगमेंट के तौर पर दिखाया जाता है. इसकी जानकारी नीचे दी गई इमेज में मौजूद है.
बाईं ओर दिखाई गई पहली स्क्रीन पर, ट्रैकिंग शुरू और बंद करने के बटन हैं. स्क्रीन पर, उपयोगकर्ता की नींद से जुड़ा कुछ डेटा दिखाया गया है. मिटाएं बटन दबाने पर, ऐप्लिकेशन ने उपयोगकर्ता के लिए जो भी डेटा इकट्ठा किया है वह हमेशा के लिए मिट जाता है. दाईं ओर दिखाई गई दूसरी स्क्रीन, नींद की क्वालिटी की रेटिंग चुनने के लिए है.
इस ऐप्लिकेशन को इस तरह से डिज़ाइन किया गया है कि यह यूज़र इंटरफ़ेस (यूआई) कंट्रोलर, ViewModel
, LiveData
, और Room
डेटाबेस का इस्तेमाल करके, नींद के डेटा को सेव कर सके.
नींद का डेटा, RecyclerView
में दिखाया जाता है. इस कोडलैब में, आपको DiffUtil
और RecyclerView
के लिए डेटा-बाइंडिंग वाला हिस्सा बनाने का तरीका बताया गया है. इस कोडलैब के बाद, आपका ऐप्लिकेशन पहले जैसा ही दिखेगा. हालांकि, यह ज़्यादा असरदार होगा. साथ ही, इसे स्केल करना और बनाए रखना आसान होगा.
पिछले कोडलैब में इस्तेमाल किए गए SleepTracker ऐप्लिकेशन का इस्तेमाल जारी रखा जा सकता है. इसके अलावा, GitHub से RecyclerViewDiffUtilDataBinding-Starter ऐप्लिकेशन डाउनलोड किया जा सकता है.
- अगर ज़रूरत हो, तो GitHub से RecyclerViewDiffUtilDataBinding-Starter ऐप्लिकेशन डाउनलोड करें और Android Studio में प्रोजेक्ट खोलें.
- ऐप्लिकेशन चलाएं.
SleepNightAdapter.kt
फ़ाइल खोलें.- ऐप्लिकेशन के स्ट्रक्चर के बारे में जानने के लिए, कोड की जांच करें. उपयोगकर्ता को नींद का डेटा दिखाने के लिए, अडैप्टर पैटर्न के साथ
RecyclerView
का इस्तेमाल करने के बारे में फिर से जानने के लिए, यहां दिया गया डायग्राम देखें.
- उपयोगकर्ता के इनपुट के आधार पर, ऐप्लिकेशन
SleepNight
ऑब्जेक्ट की सूची बनाता है. हरSleepNight
ऑब्जेक्ट, एक रात की नींद, उसकी अवधि, और क्वालिटी के बारे में बताता है. SleepNightAdapter
,SleepNight
ऑब्जेक्ट की सूची को इस तरह से बदलता है किRecyclerView
इसका इस्तेमाल कर सके और इसे दिखा सके.SleepNightAdapter
अडैप्टर,ViewHolders
बनाता है. इसमें रीसाइकलर व्यू के लिए व्यू, डेटा, और मेटा जानकारी होती है, ताकि डेटा दिखाया जा सके.RecyclerView
,SleepNightAdapter
का इस्तेमाल करके यह तय करता है कि कितने आइटम दिखाने हैं (getItemCount()
).RecyclerView
,onCreateViewHolder()
औरonBindViewHolder()
का इस्तेमाल करके, डेटा से जुड़े व्यू होल्डर को दिखाता है.
notifyDataSetChanged() तरीका असरदार नहीं है
RecyclerView
को यह बताने के लिए कि सूची में मौजूद किसी आइटम में बदलाव हुआ है और उसे अपडेट करने की ज़रूरत है, मौजूदा कोड SleepNightAdapter
में notifyDataSetChanged()
को कॉल करता है. इसे यहां दिखाया गया है.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
हालांकि, notifyDataSetChanged()
से RecyclerView
को पता चलता है कि पूरी सूची अमान्य हो सकती है. इस वजह से, RecyclerView
सूची में मौजूद हर आइटम को फिर से बाइंड करता है और फिर से बनाता है. इसमें वे आइटम भी शामिल हैं जो स्क्रीन पर नहीं दिखते. यह बहुत ज़्यादा गै़र-ज़रूरी काम है. बड़ी या मुश्किल सूचियों के लिए, इस प्रोसेस में इतना समय लग सकता है कि उपयोगकर्ता के सूची में स्क्रोल करने पर, डिसप्ले फ़्लिकर या रुक-रुक कर चले.
इस समस्या को ठीक करने के लिए, RecyclerView
को बताएं कि असल में क्या बदलाव हुआ है. इसके बाद, RecyclerView
सिर्फ़ उन व्यू को अपडेट कर सकता है जो स्क्रीन पर बदले हैं.
RecyclerView
में, किसी एक एलिमेंट को अपडेट करने के लिए रिच एपीआई है. RecyclerView
को यह बताने के लिए कि किसी आइटम में बदलाव हुआ है, notifyItemChanged()
का इस्तेमाल किया जा सकता है. साथ ही, जोड़े गए, हटाए गए या एक जगह से दूसरी जगह ले जाए गए आइटम के लिए भी इसी तरह के फ़ंक्शन का इस्तेमाल किया जा सकता है. इसे मैन्युअल तरीके से भी किया जा सकता है, लेकिन यह काम आसान नहीं होगा. इसमें काफ़ी कोड शामिल हो सकता है.
हालांकि, इससे बेहतर तरीका भी है.
DiffUtil एक असरदार टूल है और यह आपके लिए मुश्किल काम को आसान बना देता है
RecyclerView
में DiffUtil
नाम की एक क्लास होती है. इसका इस्तेमाल दो सूचियों के बीच अंतर का हिसाब लगाने के लिए किया जाता है. DiffUtil
, पुरानी और नई सूची की तुलना करके यह पता लगाता है कि दोनों में क्या अंतर है. यह उन आइटम का पता लगाता है जिन्हें जोड़ा, हटाया या बदला गया है. इसके बाद, यह Eugene W. Myers's difference algorithm का इस्तेमाल करता है. इससे यह पता चलता है कि नई सूची बनाने के लिए, पुरानी सूची में कम से कम कितने बदलाव करने होंगे.
DiffUtil
को यह पता चल जाता है कि क्या बदला है. इसके बाद, DiffUtil
उस जानकारी का इस्तेमाल करके, सिर्फ़ उन आइटम को अपडेट कर सकता है जिन्हें बदला गया है, जोड़ा गया है, हटाया गया है या जिनकी जगह बदली गई है. यह पूरी सूची को फिर से बनाने से ज़्यादा असरदार है.RecyclerView
इस टास्क में, आपको SleepNightAdapter
को अपग्रेड करके DiffUtil
का इस्तेमाल करना है, ताकि डेटा में हुए बदलावों के लिए RecyclerView
को ऑप्टिमाइज़ किया जा सके.
पहला चरण: SleepNightDiffCallback लागू करना
DiffUtil
क्लास की सुविधाओं का इस्तेमाल करने के लिए, DiffUtil.ItemCallback
को एक्सटेंड करें.
SleepNightAdapter.kt
खोलें.SleepNightAdapter
के लिए पूरी क्लास डेफ़िनिशन के नीचे,SleepNightDiffCallback
नाम की नई टॉप-लेवल क्लास बनाएं. यह क्लासDiffUtil.ItemCallback
को बढ़ाती है.SleepNight
को सामान्य पैरामीटर के तौर पर पास करें.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
- कर्सर को
SleepNightDiffCallback
क्लास के नाम में रखें. Alt+Enter
(Mac परOption+Enter
) दबाएं और सदस्यों को लागू करें चुनें.- खुलने वाले डायलॉग बॉक्स में,
areItemsTheSame()
औरareContentsTheSame()
तरीकों को चुनने के लिए, Shift दबाकर बाईं ओर क्लिक करें. इसके बाद, ठीक है पर क्लिक करें.
इससे, नीचे दिखाए गए तरीके से,SleepNightDiffCallback
में दोनों तरीकों के लिए स्टब जनरेट होते हैं.DiffUtil
इन दो तरीकों का इस्तेमाल करके यह पता लगाता है कि सूची और आइटम में क्या बदलाव हुए हैं.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
areItemsTheSame()
के अंदर,TODO
को ऐसे कोड से बदलें जो यह जांच करता हो कि पास किए गए दोSleepNight
आइटम,oldItem
औरnewItem
एक जैसे हैं या नहीं. अगर आइटम काnightId
एक जैसा है, तो इसका मतलब है कि वे एक ही आइटम हैं. इसलिए,true
एट्रिब्यूट की वैल्यू के तौर पर 'हां' सेट करें. अगर ऐसा नहीं है, तोfalse
दिखाएं.DiffUtil
इस टेस्ट का इस्तेमाल यह पता लगाने के लिए करता है कि कोई आइटम जोड़ा गया, हटाया गया या उसे किसी दूसरी जगह ले जाया गया.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
}
areContentsTheSame()
के अंदर, देखें किoldItem
औरnewItem
में एक ही डेटा है या नहीं. इसका मतलब है कि देखें कि वे बराबर हैं या नहीं. यह समानता जांच, सभी फ़ील्ड की जांच करेगी, क्योंकिSleepNight
एक डेटा क्लास है.Data
क्लास, आपके लिएequals
और कुछ अन्य तरीकों को अपने-आप तय करती हैं. अगरoldItem
औरnewItem
के बीच कोई अंतर है, तो यह कोडDiffUtil
को बताता है कि आइटम अपडेट कर दिया गया है.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem
}
बदलती हुई सूची को दिखाने के लिए, RecyclerView
का इस्तेमाल करना एक सामान्य पैटर्न है. RecyclerView
, ListAdapter
नाम की एक अडैप्टर क्लास उपलब्ध कराता है. इससे आपको एक ऐसा RecyclerView
अडैप्टर बनाने में मदद मिलती है जो किसी सूची पर आधारित होता है.
ListAdapter
आपके लिए सूची को ट्रैक करता है और सूची अपडेट होने पर अडैप्टर को सूचना देता है.
पहला चरण: अपने अडैप्टर को ListAdapter में बदलें
SleepNightAdapter.kt
फ़ाइल में,SleepNightAdapter
का क्लास सिग्नेचर बदलकरListAdapter
को बढ़ाएं.- अगर कहा जाए, तो
androidx.recyclerview.widget.ListAdapter
इंपोर्ट करें. SleepNight
कोListAdapter
फ़ंक्शन में पहले आर्ग्युमेंट के तौर पर जोड़ें. इसेSleepNightAdapter.ViewHolder
से पहले जोड़ें.- कंस्ट्रक्टर में
SleepNightDiffCallback()
को पैरामीटर के तौर पर जोड़ें.ListAdapter
इसका इस्तेमाल करके यह पता लगाएगा कि सूची में क्या बदलाव हुआ है. आपकी पूरी की गईSleepNightAdapter
क्लास का सिग्नेचर, यहां दिखाए गए सिग्नेचर की तरह दिखना चाहिए.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
SleepNightAdapter
क्लास में, सेटर के साथ-साथdata
फ़ील्ड को मिटाएं. अब आपको इसकी ज़रूरत नहीं है, क्योंकिListAdapter
आपके लिए लिस्ट को ट्रैक करता है.getItemCount()
के ओवरराइड को मिटा दें, क्योंकिgetItemCount()
आपके लिए इस तरीके को लागू करता है.ListAdapter
onBindViewHolder()
में मौजूद गड़बड़ी को ठीक करने के लिए,item
वैरिएबल में बदलाव करें.item
पाने के लिएdata
का इस्तेमाल करने के बजाय,ListAdapter
के ज़रिए उपलब्ध कराए गएgetItem(position)
तरीके को कॉल करें.
val item = getItem(position)
दूसरा चरण: सूची को अपडेट रखने के लिए submitList() का इस्तेमाल करना
आपके कोड को ListAdapter
को यह बताना होगा कि बदली हुई सूची कब उपलब्ध है. ListAdapter
, submitList()
नाम का एक तरीका उपलब्ध कराता है. इससे ListAdapter
को यह सूचना मिलती है कि सूची का नया वर्शन उपलब्ध है. इस तरीके को कॉल करने पर, ListAdapter
नई सूची की तुलना पुरानी सूची से करता है. साथ ही, उन आइटम का पता लगाता है जिन्हें जोड़ा, हटाया, बदला या एक जगह से दूसरी जगह ले जाया गया है. इसके बाद, ListAdapter
, RecyclerView
पर दिखाए गए आइटम अपडेट करता है.
SleepTrackerFragment.kt
खोलें.onCreateView()
में,sleepTrackerViewModel
पर मौजूद ऑब्ज़र्वर में, उस गड़बड़ी का पता लगाएं जिसमें आपने जिसdata
वैरिएबल को मिटाया है उसका रेफ़रंस दिया गया है.adapter.data = it
कोadapter.submitList(it)
पर कॉल करने की सुविधा से बदलें. अपडेट किया गया कोड यहां दिया गया है.
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
- ऐप्लिकेशन चलाएं. यह तेज़ी से चलता है. अगर आपकी सूची छोटी है, तो हो सकता है कि आपको यह बदलाव न दिखे.
इस टास्क में, डेटा बाइंडिंग सेट अप करने के लिए, पिछले कोडलैब में इस्तेमाल की गई तकनीक का इस्तेमाल किया जाता है. साथ ही, findViewById()
को कॉल करने की सुविधा हटा दी जाती है.
पहला चरण: लेआउट फ़ाइल में डेटा बाइंडिंग जोड़ना
- टेक्स्ट टैब में जाकर,
list_item_sleep_night.xml
लेआउट फ़ाइल खोलें. - कर्सर को
ConstraintLayout
टैग पर रखें औरAlt+Enter
(Mac परOption+Enter
) दबाएं. इसके बाद, इंटेंट मेन्यू ("तुरंत ठीक करें" मेन्यू) खुलता है. - डेटा बाइंडिंग लेआउट में बदलें को चुनें. इससे लेआउट को
<layout>
में रैप किया जाता है और इसके अंदर<data>
टैग जोड़ा जाता है. - अगर ज़रूरी हो, तो वापस सबसे ऊपर जाएं. इसके बाद,
<data>
टैग में,sleep
नाम का वैरिएबल घोषित करें. - इसके
type
कोSleepNight
,com.example.android.trackmysleepquality.database.SleepNight
का पूरी तरह क्वालिफ़ाइड नाम बनाएं. आपका पूरा किया गया<data>
टैग, नीचे दिए गए उदाहरण की तरह दिखना चाहिए.
<data>
<variable
name="sleep"
type="com.example.android.trackmysleepquality.database.SleepNight"/>
</data>
Binding
ऑब्जेक्ट को बनाने के लिए, Build > Clean Project को चुनें. इसके बाद, Build > Rebuild Project को चुनें. (अगर आपको अब भी समस्याएं आ रही हैं, तो फ़ाइल > कैश मेमोरी मिटाएं / फिर से शुरू करें चुनें.)ListItemSleepNightBinding
बाइंडिंग ऑब्जेक्ट और उससे जुड़ा कोड, प्रोजेक्ट की जनरेट की गई फ़ाइलों में जोड़ दिया जाता है.
दूसरा चरण: डेटा बाइंडिंग का इस्तेमाल करके आइटम लेआउट को बड़ा करना
SleepNightAdapter.kt
खोलें.ViewHolder
क्लास में,from()
तरीका ढूंढें.view
वैरिएबल का एलान मिटाएं.
मिटाने का कोड:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
view
वैरिएबल की जगह पर,binding
नाम का एक नया वैरिएबल तय करें. यहListItemSleepNightBinding
बाइंडिंग ऑब्जेक्ट को बढ़ाता है. इसे नीचे दिखाया गया है. बाइंडिंग ऑब्जेक्ट को ज़रूरी तौर पर इंपोर्ट करें.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
- फ़ंक्शन के आखिर में,
view
दिखाने के बजायbinding
दिखाएं.
return ViewHolder(binding)
- गड़बड़ी को ठीक करने के लिए, अपने कर्सर को
binding
शब्द पर रखें. इंटेंशन मेन्यू खोलने के लिए,Alt+Enter
(Mac परOption+Enter
) दबाएं.
- क्लास 'ViewHolder' के मुख्य कंस्ट्रक्टर के पैरामीटर 'itemView' के टाइप को 'ListItemSleepNightBinding' में बदलें को चुनें. इससे
ViewHolder
क्लास के पैरामीटर टाइप को अपडेट किया जाता है.
- हस्ताक्षर में हुए बदलाव को देखने के लिए,
ViewHolder
की क्लास डेफ़िनिशन तक ऊपर की ओर स्क्रोल करें. आपकोitemView
के लिए गड़बड़ी दिख रही है, क्योंकि आपनेfrom()
तरीके मेंitemView
कोbinding
में बदल दिया है.ViewHolder
क्लास की परिभाषा में,itemView
के किसी एक उदाहरण पर राइट क्लिक करें. इसके बाद, रीफ़ैक्टर करें > नाम बदलें को चुनें. नाम बदलकरbinding
कर दें. - कंस्ट्रक्टर पैरामीटर
binding
को प्रॉपर्टी बनाने के लिए, इसके पहलेval
जोड़ें. - पैरंट क्लास
RecyclerView.ViewHolder
को कॉल करते समय, पैरामीटर कोbinding
से बदलकरbinding.root
करें. आपकोView
पास करना होगा. साथ ही,binding.root
आपके आइटम लेआउट में रूटConstraintLayout
है. - क्लास का एलान करने के बाद, आपका कोड यहां दिए गए कोड जैसा दिखना चाहिए.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
आपको findViewById()
पर किए गए कॉल के लिए भी गड़बड़ी दिखती है. इसे ठीक करने के लिए, यह तरीका आज़माएं.
तीसरा चरण: findViewById() को बदलें
अब findViewById()
के बजाय binding
ऑब्जेक्ट का इस्तेमाल करने के लिए, sleepLength
, quality
, और qualityImage
प्रॉपर्टी अपडेट की जा सकती हैं.
sleepLength
,qualityString
, औरqualityImage
के इनिशियलाइज़ेशन को बदलकर,binding
ऑब्जेक्ट के व्यू का इस्तेमाल करें. इसके लिए, यहां दिया गया तरीका अपनाएं. इसके बाद, आपके कोड में कोई और गड़बड़ी नहीं दिखनी चाहिए.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
बाइंडिंग ऑब्जेक्ट का इस्तेमाल करने पर, आपको sleepLength
, quality
, और qualityImage
प्रॉपर्टी को अब तय करने की ज़रूरत नहीं है. DataBinding
लुकअप को कैश मेमोरी में सेव करेगा. इसलिए, इन प्रॉपर्टी को घोषित करने की ज़रूरत नहीं है.
sleepLength
,quality
, औरqualityImage
प्रॉपर्टी के नामों पर राइट क्लिक करें. Refactor > Inline चुनें याControl+Command+N
(Mac परOption+Command+N
) दबाएं.- अपना ऐप्लिकेशन चलाएं. अगर आपके प्रोजेक्ट में गड़बड़ियां हैं, तो आपको उसे क्लीन और फिर से बनाना पड़ सकता है.
इस टास्क में, आपको अपने ऐप्लिकेशन को अपग्रेड करना है, ताकि वह डेटा बाइंडिंग और बाइंडिंग अडैप्टर का इस्तेमाल करके, व्यू में डेटा सेट कर सके.
पिछले कोडलैब में, आपने Transformations
क्लास का इस्तेमाल करके LiveData
लिया था. साथ ही, टेक्स्ट व्यू में दिखाने के लिए फ़ॉर्मैट की गई स्ट्रिंग जनरेट की थीं. हालांकि, अगर आपको अलग-अलग टाइप या जटिल टाइप बाइंड करने हैं, तो बाइंडिंग अडैप्टर दिए जा सकते हैं. इससे डेटा बाइंडिंग को उन टाइप का इस्तेमाल करने में मदद मिलती है. बाइंडिंग अडैप्टर ऐसे अडैप्टर होते हैं जो आपके डेटा को लेते हैं और उसे ऐसे फ़ॉर्मैट में बदलते हैं जिसका इस्तेमाल डेटा बाइंडिंग, व्यू को बाइंड करने के लिए कर सकती है. जैसे, टेक्स्ट या इमेज.
आपको तीन बाइंडिंग अडैप्टर लागू करने हैं. इनमें से एक अडैप्टर क्वालिटी इमेज के लिए और एक-एक अडैप्टर हर टेक्स्ट फ़ील्ड के लिए होगा. संक्षेप में, बाइंडिंग अडैप्टर को तय करने के लिए, एक ऐसा तरीका तय करें जो किसी आइटम और व्यू को लेता हो. साथ ही, उसे @BindingAdapter
के साथ एनोटेट करें. तरीके के मुख्य हिस्से में, ट्रांसफ़ॉर्मेशन लागू किया जाता है. Kotlin में, डेटा पाने वाली व्यू क्लास पर एक्सटेंशन फ़ंक्शन के तौर पर बाइंडिंग अडैप्टर लिखा जा सकता है.
पहला चरण: बाइंडिंग अडैप्टर बनाना
ध्यान दें कि आपको इस चरण में कई क्लास इंपोर्ट करनी होंगी. इन्हें अलग-अलग नहीं दिखाया जाएगा.
SleepNightAdapater.kt
खोलें.ViewHolder
क्लास में,bind()
तरीका ढूंढें और याद करें कि यह तरीका क्या करता है. आपकोbinding.sleepLength
,binding.quality
, औरbinding.qualityImage
की वैल्यू का हिसाब लगाने वाले कोड को लेना होगा. इसके बाद, इसे अडैप्टर के अंदर इस्तेमाल करना होगा. (अभी के लिए, कोड को ऐसे ही रहने दें. इसे बाद में बदला जाएगा.)sleeptracker
पैकेज में,BindingUtils.kt
नाम की फ़ाइल बनाएं और उसे खोलें.TextView
परsetSleepDurationFormatted
नाम के एक्सटेंशन फ़ंक्शन का एलान करें और उसमेंSleepNight
पास करें. यह फ़ंक्शन, नींद की अवधि का हिसाब लगाने और उसे फ़ॉर्मैट करने के लिए आपके अडैप्टर के तौर पर काम करेगा.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
setSleepDurationFormatted
के मुख्य हिस्से में, डेटा को व्यू से उसी तरह बाइंड करें जिस तरह आपनेViewHolder.bind()
में किया था.convertDurationToFormatted()
को कॉल करें. इसके बाद,TextView
केtext
को फ़ॉर्मैट किए गए टेक्स्ट पर सेट करें. (यहTextView
पर एक एक्सटेंशन फ़ंक्शन है. इसलिए,text
प्रॉपर्टी को सीधे तौर पर ऐक्सेस किया जा सकता है.)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
- डेटा बाइंडिंग को इस बाइंडिंग अडैप्टर के बारे में बताने के लिए, फ़ंक्शन को
@BindingAdapter
के साथ एनोटेट करें. - यह फ़ंक्शन,
sleepDurationFormatted
एट्रिब्यूट के लिए अडैप्टर है. इसलिए,@BindingAdapter
को@BindingAdapter
के लिए आर्ग्युमेंट के तौर पर पास करें.sleepDurationFormatted
@BindingAdapter("sleepDurationFormatted")
- दूसरा अडैप्टर,
SleepNight
ऑब्जेक्ट में मौजूद वैल्यू के आधार पर नींद की क्वालिटी सेट करता है.TextView
परsetSleepQualityString()
नाम का एक्सटेंशन फ़ंक्शन बनाएं और उसमेंSleepNight
पास करें. - बॉडी में, डेटा को व्यू से उसी तरह बाइंड करें जिस तरह आपने
ViewHolder.bind()
में किया था.convertNumericQualityToString
को कॉल करो औरtext
सेट करो. - फ़ंक्शन को
@BindingAdapter("sleepQualityString")
से एनोटेट करें.
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
- तीसरा बाइंडिंग अडैप्टर, इमेज व्यू पर इमेज सेट करता है. नीचे दिए गए तरीके से,
ImageView
पर एक्सटेंशन फ़ंक्शन बनाएं,setSleepImage
को कॉल करें, औरViewHolder.bind()
से कोड का इस्तेमाल करें.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
setImageResource(when (item.sleepQuality) {
0 -> R.drawable.ic_sleep_0
1 -> R.drawable.ic_sleep_1
2 -> R.drawable.ic_sleep_2
3 -> R.drawable.ic_sleep_3
4 -> R.drawable.ic_sleep_4
5 -> R.drawable.ic_sleep_5
else -> R.drawable.ic_sleep_active
})
}
दूसरा चरण: SleepNightAdapter को अपडेट करना
SleepNightAdapter.kt
खोलें.bind()
तरीके में मौजूद हर चीज़ को मिटा दें, क्योंकि अब डेटा बाइंडिंग और नए अडैप्टर का इस्तेमाल करके, यह काम किया जा सकता है.
fun bind(item: SleepNight) {
}
bind()
के अंदर,item
को स्लीप असाइन करें, क्योंकि आपको बाइंडिंग ऑब्जेक्ट को अपने नएSleepNight
के बारे में बताना है.
binding.sleep = item
- उस लाइन के नीचे,
binding.executePendingBindings()
जोड़ें. यह कॉल एक ऑप्टिमाइज़ेशन है, जो डेटा बाइंडिंग से तुरंत सभी लंबित बाइंडिंग को लागू करने के लिए कहता है.RecyclerView
में बाइंडिंग अडैप्टर का इस्तेमाल करते समय,executePendingBindings()
को कॉल करना हमेशा अच्छा होता है. इससे व्यू का साइज़ तय करने में थोड़ी तेज़ी आ सकती है.
binding.executePendingBindings()
तीसरा चरण: एक्सएमएल लेआउट में बाइंडिंग जोड़ना
list_item_sleep_night.xml
खोलें.ImageView
में,app
प्रॉपर्टी जोड़ें. इसका नाम, इमेज सेट करने वाले बाइंडिंग अडैप्टर के नाम जैसा होना चाहिए. नीचे दिखाए गए तरीके से,sleep
वैरिएबल पास करें.
यह प्रॉपर्टी, अडैप्टर के ज़रिए व्यू और बाइंडिंग ऑब्जेक्ट के बीच कनेक्शन बनाती है. जब भीsleepImage
का रेफ़रंस दिया जाता है, तब अडैप्टर,SleepNight
से डेटा को अडैप्ट कर लेता है.
app:sleepImage="@{sleep}"
sleep_length
औरquality_string
टेक्स्ट व्यू के लिए भी ऐसा ही करें. जब भीsleepDurationFormatted
याsleepQualityString
का रेफ़रंस दिया जाता है, तब अडैप्टर,SleepNight
से डेटा को अडैप्ट कर लेंगे.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
- अपना ऐप्लिकेशन चलाएं. यह ठीक उसी तरह काम करता है जैसे पहले करता था. डेटा में बदलाव होने पर, बाइंडिंग अडैप्टर व्यू को फ़ॉर्मैट करने और अपडेट करने का काम करते हैं. इससे
ViewHolder
आसान हो जाता है. साथ ही, कोड को पहले से बेहतर स्ट्रक्चर मिलता है.
आपने पिछली कुछ कसरतों के लिए एक ही सूची दिखाई है. ऐसा इसलिए किया गया है, ताकि आपको यह दिखाया जा सके कि Adapter
इंटरफ़ेस की मदद से, कोड को कई अलग-अलग तरीकों से बनाया जा सकता है. आपका कोड जितना जटिल होगा, उसे अच्छी तरह से डिज़ाइन करना उतना ही ज़रूरी होगा. प्रोडक्शन ऐप्लिकेशन में, इन पैटर्न और अन्य पैटर्न का इस्तेमाल RecyclerView
के साथ किया जाता है. ये सभी पैटर्न काम करते हैं और हर पैटर्न के अपने फ़ायदे हैं. आपको कौनसा विकल्प चुनना है, यह इस बात पर निर्भर करता है कि आपको क्या बनाना है.
बधाई हो! अब तक, आपने Android पर RecyclerView
का इस्तेमाल करना सीख लिया होगा.
Android Studio प्रोजेक्ट: RecyclerViewDiffUtilDataBinding.
DiffUtil
:
RecyclerView
मेंDiffUtil
नाम की एक क्लास होती है. इसका इस्तेमाल दो सूचियों के बीच अंतर का हिसाब लगाने के लिए किया जाता है.DiffUtil
मेंItemCallBack
नाम की एक क्लास है. दो सूचियों के बीच का अंतर पता लगाने के लिए, आपको इस क्लास को बढ़ाना होगा.ItemCallback
क्लास में, आपकोareItemsTheSame()
औरareContentsTheSame()
तरीकों को ओवरराइड करना होगा.
ListAdapter
:
- सूची को मैनेज करने की कुछ सुविधाएं बिना किसी शुल्क के पाने के लिए,
RecyclerView.Adapter
के बजायListAdapter
क्लास का इस्तेमाल करें. हालांकि, अगरListAdapter
का इस्तेमाल किया जाता है, तो आपको अन्य लेआउट के लिए अपना अडैप्टर लिखना होगा. इसलिए, यह कोडलैब आपको ऐसा करने का तरीका दिखाता है. - Android Studio में इंटेंशन मेन्यू खोलने के लिए, कर्सर को कोड के किसी भी आइटम पर रखें और
Alt+Enter
(Mac परOption+Enter
) दबाएं. यह मेन्यू, कोड को फिर से व्यवस्थित करने और तरीकों को लागू करने के लिए स्टब बनाने में खास तौर पर मददगार होता है. यह मेन्यू, कॉन्टेक्स्ट के हिसाब से काम करता है. इसलिए, सही मेन्यू पाने के लिए आपको कर्सर को सही जगह पर रखना होगा.
डेटा बाइंडिंग:
- आइटम लेआउट में डेटा बाइंडिंग का इस्तेमाल करके, डेटा को व्यू से बाइंड करें.
बाइंडिंग अडैप्टर:
- आपने पहले
Transformations
का इस्तेमाल करके, डेटा से स्ट्रिंग बनाई थीं. अगर आपको अलग-अलग या जटिल टाइप के डेटा को बाइंड करना है, तो बाइंडिंग अडैप्टर उपलब्ध कराएं. इससे डेटा बाइंडिंग को उनका इस्तेमाल करने में मदद मिलेगी. - बाइंडिंग अडैप्टर को तय करने के लिए, एक ऐसा तरीका तय करें जो आइटम और व्यू लेता हो. साथ ही, इस तरीके को
@BindingAdapter
से एनोटेट करें. Kotlin में, बाइंडिंग अडैप्टर कोView
पर एक्सटेंशन फ़ंक्शन के तौर पर लिखा जा सकता है. उस प्रॉपर्टी का नाम पास करें जिसे अडैप्टर अडैप्ट करता है. उदाहरण के लिए:
@BindingAdapter("sleepDurationFormatted")
- एक्सएमएल लेआउट में, बाइंडिंग अडैप्टर के नाम वाली
app
प्रॉपर्टी सेट करें. डेटा के साथ वैरिएबल पास करें. उदाहरण के लिए:
.app:sleepDurationFormatted="@{sleep}"
Udacity के कोर्स:
Android डेवलपर का दस्तावेज़:
- RecyclerView की मदद से सूची बनाना
RecyclerView
DiffUtil
- डेटा बाइंडिंग लाइब्रेरी
- बाइंडिंग अडैप्टर
notifyDataSetChanged()
Transformations
अन्य संसाधन:
इस सेक्शन में, उन छात्र-छात्राओं के लिए होमवर्क असाइनमेंट की सूची दी गई है जो किसी शिक्षक के कोर्स के हिस्से के तौर पर इस कोडलैब पर काम कर रहे हैं. शिक्षक के पास ये विकल्प होते हैं:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को बताएं कि होमवर्क असाइनमेंट कैसे सबमिट किए जाते हैं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल अपनी ज़रूरत के हिसाब से कर सकते हैं. साथ ही, वे चाहें, तो कोई दूसरा होमवर्क भी दे सकते हैं.
अगर आपको यह कोडलैब खुद से पूरा करना है, तो अपनी जानकारी की जांच करने के लिए, इन होमवर्क असाइनमेंट का इस्तेमाल करें.
इन सवालों के जवाब दें
पहला सवाल
DiffUtil
का इस्तेमाल करने के लिए, इनमें से कौनसी चीज़ें ज़रूरी हैं? लागू होने वाले सभी विकल्पों को चुनें.
▢ ItemCallBack
क्लास को बढ़ाएं.
▢ बदलें areItemsTheSame()
.
▢ बदलें areContentsTheSame()
.
▢ सामानों के बीच अंतर को ट्रैक करने के लिए, डेटा बाइंडिंग का इस्तेमाल करें.
सवाल 2
बाइंडिंग अडैप्टर के बारे में इनमें से कौनसी बातें सही हैं?
▢ बाइंडिंग अडैप्टर, @BindingAdapter
एनोटेशन वाला फ़ंक्शन होता है.
▢ बाइंडिंग अडैप्टर का इस्तेमाल करके, डेटा फ़ॉर्मैटिंग को व्यू होल्डर से अलग किया जा सकता है.
▢ अगर आपको बाइंडिंग अडैप्टर का इस्तेमाल करना है, तो आपको RecyclerViewAdapter
का इस्तेमाल करना होगा.
▢ जब आपको मुश्किल डेटा को बदलना हो, तब बाइंडिंग अडैप्टर एक अच्छा विकल्प है.
सवाल 3
आपको बाइंडिंग अडैप्टर के बजाय Transformations
का इस्तेमाल कब करना चाहिए? लागू होने वाले सभी विकल्पों को चुनें.
▢ आपका डेटा सामान्य है.
▢ स्ट्रिंग को फ़ॉर्मैट किया जा रहा है.
▢ आपकी सूची बहुत लंबी है.
▢ आपके ViewHolder
में सिर्फ़ एक व्यू शामिल है.
अगला लेसन शुरू करें: