यह कोडलैब Android Kotlin के बुनियादी कोर्स में शामिल है. अगर आप कोडलैब के क्रम में काम करते हैं, तो आपको इस कोर्स का ज़्यादा से ज़्यादा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Android Kotlin से जुड़े बेसिक कोडलैब के लैंडिंग पेज पर दिए गए हैं.
परिचय
पिछले कोडलैब में आपने RecyclerView
में नींद की क्वालिटी के बारे में डेटा दिखाने के लिए, ट्रैकरMySleepquality ऐप्लिकेशन को अपडेट किया था. पहली बार RecyclerView
बनाते समय आपने जो तकनीक सीखीं, वह ज़्यादातर RecyclerViews
के लिए काफ़ी हैं. इनमें ऐसी आसान सूचियां दिखाई जाती हैं जो बहुत बड़ी न हों. हालांकि, ऐसी कई तकनीकें हैं जो RecyclerView
को बड़ी सूचियों के लिए ज़्यादा असरदार बनाती हैं. साथ ही, आपके कोड को बनाए रखना और जटिल सूचियों और ग्रिड के लिए इसे बढ़ाना आसान बनाती हैं.
इस कोडलैब में, आप पिछले कोडलैब के आधार पर, स्लीप-ट्रैकर ऐप्लिकेशन पर बनाते हैं. आप नींद के डेटा की सूची को अपडेट करने का ज़्यादा असरदार तरीका जानते हैं. साथ ही, आप RecyclerView
के साथ डेटा बाइंडिंग का इस्तेमाल करने का तरीका जानते हैं. (अगर आपके पास पिछले कोडलैब से ऐप्लिकेशन नहीं है, तो आप इस कोडलैब के लिए स्टार्टर कोड डाउनलोड कर सकते हैं.)
आपको क्या पता होना चाहिए
- किसी ऐक्टिविटी, फ़्रैगमेंट, और व्यू का इस्तेमाल करके बेसिक यूज़र इंटरफ़ेस बनाना.
- फ़्रैगमेंट के बीच नेविगेट करना और फ़्रैगमेंट के बीच डेटा पास करने के लिए,
safeArgs
का इस्तेमाल करना. - मॉडल, मॉडल फ़ैक्ट्री, बदलाव, और उनके
LiveData
की निगरानी करें. Room
डेटाबेस बनाने, डीएओ बनाने, और इकाइयों की जानकारी देने का तरीका.- डेटाबेस और लंबे समय तक चलने वाले अन्य कामों के लिए कोरूटीन इस्तेमाल करने का तरीका.
Adapter
,ViewHolder
, और आइटम लेआउट के साथ बेसिकRecyclerView
को लागू करने का तरीका.
आप इन चीज़ों के बारे में जानेंगे
RecyclerView
की ओर से दिखाई गई सूची को बेहतर तरीके से अपडेट करने के लिए,DiffUtil
का इस्तेमाल कैसे करें.RecyclerView
के साथ डेटा बाइंडिंग का इस्तेमाल करने का तरीका.- डेटा में बदलाव करने के लिए बाइंडिंग अडैप्टर का इस्तेमाल कैसे करें.
आप क्या कर पाएंगे!
- इस सीरीज़ के पिछले कोडलैब से, ShowMySleepquality ऐप्लिकेशन पर बनाएं.
DiffUtil
का इस्तेमाल करके, सूची को बेहतर तरीके से अपडेट करने के लिए,SleepNightAdapter
को अपडेट करें.- डेटा बदलने के लिए बाइंडिंग अडैप्टर का इस्तेमाल करके,
RecyclerView
के लिए डेटा बाइंडिंग लागू करें.
स्लीप-ट्रैकर ऐप्लिकेशन में, फ़्रैगमेंट से दिखने वाली दो स्क्रीन होती हैं. जैसा कि नीचे दी गई इमेज में दिखाया गया है.
बाईं ओर दिखाई गई पहली स्क्रीन पर, ट्रैकिंग शुरू और बंद करने के लिए बटन दिए गए हैं. स्क्रीन पर उपयोगकर्ता के सोने के कुछ डेटा की जानकारी दिखती है. हटाएं बटन, उपयोगकर्ता के लिए ऐप्लिकेशन के ज़रिए इकट्ठा किया गया सारा डेटा हमेशा के लिए मिटा देता है. दाईं ओर दिखाई गई दूसरी स्क्रीन, अच्छी क्वालिटी वाली रेटिंग चुनने के लिए है.
इस ऐप्लिकेशन को यूज़र इंटरफ़ेस (यूआई) कंट्रोलर, ViewModel
, और LiveData
के साथ-साथ Room
डेटाबेस का इस्तेमाल करके, नींद से जुड़े डेटा को बनाए रखने के लिए डिज़ाइन किया गया है.
नींद का डेटा RecyclerView
में दिखेगा. इस कोडलैब में, आप RecyclerView
के लिए DiffUtil
और डेटा-बाइंडिंग वाला हिस्सा बनाते हैं. इस कोडलैब के बाद, आपका ऐप्लिकेशन काफ़ी हद तक एक जैसा दिखेगा. हालांकि, यह काफ़ी आसान और मापने में आसान होगा.
आप पिछले कोडलैब से 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()
की मदद से, व्यू होल्डर दिखाए जा सकते हैं.
AndroidManifestDataSetChanged() विधि अक्षम है
RecyclerView
को यह बताने के लिए कि सूची का कोई आइटम बदल गया है और उसे अपडेट करने की ज़रूरत है, मौजूदा कोड notifyDataSetChanged()
को SleepNightAdapter
में कॉल करता है, जैसा कि नीचे दिखाया गया है.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
हालांकि, notifyDataSetChanged()
से RecyclerView
को यह पता चलता है कि पूरी सूची अमान्य है. ऐसा करने से, RecyclerView
सूची के हर आइटम को फिर से पिन करता है और उसे फिर से दिखाता है. इनमें वे आइटम भी शामिल होते हैं जो स्क्रीन पर नहीं दिखते. यह बहुत मेहनत का काम है. बड़ी या जटिल सूचियों के लिए, इस प्रोसेस में इतना समय लग सकता है कि उपयोगकर्ता सूची को स्क्रोल करते समय डिसप्ले फ़्लिकर या स्टटर कर लेता है.
इस समस्या को ठीक करने के लिए, आप RecyclerView
को सटीक तौर पर बता सकते हैं कि क्या बदलाव हुए हैं. इसके बाद, RecyclerView
सिर्फ़ उन व्यू को अपडेट कर सकता है जो स्क्रीन पर बदले गए हैं.
RecyclerView
में किसी एक एलिमेंट को अपडेट करने के लिए, एक रिच एपीआई है. आप RecyclerView
को यह बताने के लिए notifyItemChanged()
का इस्तेमाल कर सकते हैं कि किसी आइटम को बदल दिया गया है. साथ ही, आप जोड़े गए, हटाए गए या ले जाए गए आइटम के लिए, मिलते-जुलते फ़ंक्शन का इस्तेमाल कर सकते हैं. आप यह सब मैन्युअल रूप से कर सकते हैं, लेकिन यह काम सामान्य नहीं होगा. इसमें बहुत ज़्यादा कोड शामिल हो सकता है.
सबसे अच्छी बात यह है कि #39; एक बेहतर तरीका है.
DiffUtil बेहतर तरीके से काम करता है और आपके लिए कड़ी मेहनत करता है
RecyclerView
के पास DiffUtil
नाम की एक क्लास है, जो दो सूचियों के बीच के फ़र्क़ का हिसाब लगाती है. DiffUtil
एक पुरानी सूची और एक नई सूची तैयार करती है, जिससे पता चलता है कि सभी के लिए क्या अलग है. यह ऐसे आइटम को ढूंढता है जिन्हें जोड़ा गया, हटाया गया था या जिनमें बदलाव किया गया था. इसके बाद, यह एल्गोरिदम यूजीन डब्ल्यू मायर' के बीच अंतर का एल्गोरिदम पता करता है.
DiffUtil
को यह पता चलने पर कि क्या बदलाव हुए हैं, RecyclerView
उस जानकारी का इस्तेमाल सिर्फ़ उन आइटम को अपडेट करने के लिए कर सकता है जिनमें बदलाव किया गया हो, उन्हें जोड़ा गया हो, हटाया गया हो या किसी दूसरी जगह ले जाया गया हो. यह पूरी सूची को फिर से तैयार करने के मुकाबले ज़्यादा असरदार होता है.
इस टास्क को RecyclerView
में ऑप्टिमाइज़ करने के लिए, SleepNightAdapter
को अपग्रेड करें, ताकि डेटा में होने वाले बदलावों के लिए, RecyclerView
को ऑप्टिमाइज़ किया जा सके.
पहला चरण: SleepNightDiffCallback लागू करना
DiffUtil
क्लास की सुविधा इस्तेमाल करने के लिए, DiffUtil.ItemCallback
को बढ़ाएं.
SleepNightAdapter.kt
खोलें.SleepNightAdapter
के लिए फ़ुल क्लास परिभाषा के नीचे,SleepNightDiffCallback
नाम की एक नई टॉप-लेवल क्लास बनाएं, जोDiffUtil.ItemCallback
को बढ़ाती है.SleepNight
को जेनरिक पैरामीटर के तौर पर पास करें.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
- कर्सर को
SleepNightDiffCallback
क्लास के नाम में रखें. Alt+Enter
(Option+Enter
Mac पर देखें) और सदस्य लागू करें.- डायलॉग बॉक्स खुलने पर,
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
अडैप्टर बनाता है. इस अडैप्टर के बाद RecyclerView
होता है.
ListAdapter
आपके लिए सूची पर नज़र रखता है और सूची अपडेट होने पर अडैप्टर को सूचना देता है.
पहला चरण: ListAdapter इस्तेमाल करने के लिए, अडैप्टर को बदलना
ListAdapter
को बढ़ाने के लिए,SleepNightAdapter.kt
फ़ाइल मेंSleepNightAdapter
का क्लास हस्ताक्षर बदलें.- अगर कहा जाए, तो
androidx.recyclerview.widget.ListAdapter
इंपोर्ट करें. SleepNightAdapter.ViewHolder
मेंSleepNight
कोListAdapter
में पहले आर्ग्युमेंट के तौर पर जोड़ें.SleepNightDiffCallback()
को कंस्ट्रक्टर में पैरामीटर के रूप में जोड़ें.ListAdapter
इसका इस्तेमाल यह जानने के लिए करेगा कि सूची में क्या बदलाव हुआ है. कक्षा खत्म होने के बाद, आपकाSleepNightAdapter
हस्ताक्षर नीचे दिखाई देना चाहिए.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
SleepNightAdapter
क्लास के अंदर, सेटर के साथ-साथdata
फ़ील्ड को मिटा दें. आपको अब इसकी ज़रूरत नहीं है, क्योंकिListAdapter
आपके लिए सूची का ट्रैक रखता है.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
वैरिएबल है जिसे आपने और #39;मिटाया है.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
ऑब्जेक्ट को ज़बरदस्ती बनाने के लिए, Create > Clean Project चुनें. इसके बाद, Create > प्रोजेक्ट दोबारा बनाएं चुनें. (अगर आपको अब भी समस्याएं आ रही हैं, तो फ़ाइल > कैश मेमोरी चालू करें / रीस्टार्ट करें चुनें.)ListItemSleepNightBinding
बाइंडिंग ऑब्जेक्ट के साथ, प्रोजेक्ट और #39; जनरेट की गई फ़ाइलें प्रोजेक्ट में जोड़ दी जाती हैं.
दूसरा चरण: डेटा बाइंडिंग का इस्तेमाल करके आइटम के लेआउट को इनफ़्लेट करना
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
) दबाएं.
- पैरामीटर बदलें #39;itemView' क्लास के मुख्य कंस्ट्रक्टर का प्रकार 'ViewHolder' को 'ListItemSleepNightBinding' चुनें. इससे,
ViewHolder
क्लास के पैरामीटर टाइप को अपडेट किया जाता है.
- हस्ताक्षर में हुए बदलाव देखने के लिए,
ViewHolder
की क्लास डेफ़िनिशन तक स्क्रोल करें. आपकोitemView
के लिए गड़बड़ी दिख रही है, क्योंकि आपनेfrom()
तरीके मेंitemView
को बदलकरbinding
कर दिया है.ViewHolder
कक्षा की परिभाषा में,itemView
में से किसी एक इंस्टेंस पर दायां क्लिक करें और रीफ़ैक्टर &g; नाम बदलें को चुनें. नाम को बदलकर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() को बदलना
अब आप sleepLength
, quality
, और qualityImage
प्रॉपर्टी को findViewById()
के बजाय, binding
ऑब्जेक्ट का इस्तेमाल करने के लिए अपडेट कर सकते हैं.
- जैसा कि नीचे दिखाया गया है,
binding
ऑब्जेक्ट के व्यू का इस्तेमाल करने के लिएsleepLength
,qualityString
, औरqualityImage
के शुरू करने के तरीके को बदलें. इसके बाद, आपके कोड में और कोई गड़बड़ी नहीं दिखेगी.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
बाइंडिंग ऑब्जेक्ट के साथ, आपको अब sleepLength
, quality
, और qualityImage
प्रॉपर्टी को तय करने की ज़रूरत नहीं है. DataBinding
, लुकअप को कैश मेमोरी में सेव करेगा, इसलिए इन प्रॉपर्टी का एलान नहीं करना होगा.
sleepLength
,quality
, औरqualityImage
प्रॉपर्टी के नामों पर दायां क्लिक करें. ReACTOR > इनलाइन चुनें याControl+Command+N
(Mac परOption+Command+N
) दबाएं.- अपना ऐप्लिकेशन चलाएं. अगर आपके प्रोजेक्ट में कोई गड़बड़ी है, तो आपको अपने-आप और बिल्डिंग करना होगा.)
इस टास्क में, आप अपने ऐप्लिकेशन को अपग्रेड करते हैं, ताकि आपके व्यू में डेटा सेट करने के लिए बाइंडिंग अडैप्टर का इस्तेमाल कर सकें.
पिछले कोडलैब में, LiveData
लेने और टेक्स्ट व्यू में दिखाने के लिए, फ़ॉर्मैट की गई स्ट्रिंग जनरेट करने के लिए Transformations
क्लास का इस्तेमाल किया जाता था. हालांकि, अगर आपको अलग-अलग तरह के टाइप या कॉम्प्लेक्स टाइप को बाइंड करना है, तो बाइंडिंग बाइंडिंग का इस्तेमाल करके डेटा बाइंडिंग में उन टाइप का इस्तेमाल किया जा सकता है. बाइंडिंग अडैप्टर ऐसे अडैप्टर होते हैं जो आपका डेटा लेते हैं और उसे किसी ऐसी चीज़ में बदल देते हैं जिसका इस्तेमाल डेटा बाइंडिंग से कोई व्यू, जैसे कि टेक्स्ट या इमेज को बाइंड करने के लिए किया जा सके.
आप तीन बाइंडिंग अडैप्टर लागू करने जा रहे हैं, एक क्वालिटी इमेज के लिए और एक हर टेक्स्ट फ़ील्ड के लिए. खास जानकारी में, बाइंडिंग अडैप्टर का एलान करने के लिए एक तरीका बताया गया है, जिसमें एक आइटम और एक व्यू होता है. साथ ही, @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
को आर्ग्युमेंट के तौर पर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}"
Udcity कोर्स:
Android डेवलपर दस्तावेज़:
- RecyclerView की मदद से सूची बनाना
RecyclerView
DiffUtil
- डेटा बाइंडिंग लाइब्रेरी
- बाइंडिंग अडैप्टर
notifyDataSetChanged()
Transformations
अन्य संसाधन:
इस सेक्शन में उन छात्र-छात्राओं के लिए गृहकार्य की असाइनमेंट की सूची दी गई है जो इस कोडलैब के ज़रिए एक शिक्षक की देखरेख में कोर्स में काम कर रहे हैं. यह क्रिएटर का काम #33 पर निर्भर करता है:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को होमवर्क के असाइनमेंट सबमिट करने के तरीके के बारे में बताएं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल जितनी चाहें उतनी कम या ज़्यादा कर सकते हैं. साथ ही, उन्हें अपने हिसाब से कोई भी होमवर्क असाइन करना चाहिए.
अगर आप इस कोडलैब के ज़रिए खुद काम कर रहे हैं, तो बेझिझक इन होमवर्क असाइनमेंट का इस्तेमाल करें.
इन सवालों के जवाब दें
पहला सवाल
DiffUtil
का इस्तेमाल करने के लिए, इनमें से क्या ज़रूरी है? लागू होने वाले सभी विकल्प चुनें.
▢ ItemCallBack
क्लास बढ़ाएं.
▢ ओवरराइड करें areItemsTheSame()
.
▢ ओवरराइड करें areContentsTheSame()
.
▢ आइटम के बीच अंतर को ट्रैक करने के लिए डेटा बाइंडिंग का इस्तेमाल करें.
सवाल 2
बाइंडिंग अडैप्टर के बारे में इनमें से कौनसी बातें सही हैं?
▢ बाइंडिंग अडैप्टर, फ़ंक्शन है जिसे @BindingAdapter
के साथ एनोटेट किया गया है.
▢ बाइंडिंग अडैप्टर का इस्तेमाल करने से डेटा फ़ॉर्मैट को व्यू होल्डर से अलग किया जा सकता है.
▢ अगर आप बाइंडिंग अडैप्टर का इस्तेमाल करना चाहते हैं, तो आपको RecyclerViewAdapter
का इस्तेमाल करना होगा.
▢ बाइंडिंग अडैप्टर तब अच्छे समाधान होते हैं, जब आपको मुश्किल डेटा को बदलना होता है.
सवाल 3
आपको बाइंडिंग अडैप्टर के बजाय Transformations
का इस्तेमाल कब करना चाहिए? लागू होने वाले सभी विकल्प चुनें.
▢ आपका डेटा आसान है.
▢ आप किसी स्ट्रिंग को फ़ॉर्मैट कर रहे हैं.
▢ आपकी सूची बहुत लंबी है.
▢ ViewHolder
में सिर्फ़ एक व्यू है.
अगला लेसन शुरू करें: