این کد لبه بخشی از دوره آموزشی Android Kotlin Fundamentals است. اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت. همه کدهای دوره در صفحه فرود کد لبه های کدهای Android Kotlin Fundamentals فهرست شده اند.
مقدمه
در آزمایشگاه کد قبلی، برنامه TrackMySleepQuality را برای نمایش دادههای مربوط به کیفیت خواب در RecyclerView
بهروزرسانی کردید. تکنیک هایی که هنگام ساختن اولین RecyclerView
خود یاد گرفتید برای اکثر RecyclerViews
هایی که لیست های ساده ای را نمایش می دهند که خیلی بزرگ نیستند کافی است. با این حال، تعدادی تکنیک وجود دارد که RecyclerView
را برای لیستهای بزرگ کارآمدتر میکند و حفظ و گسترش کد شما را برای فهرستها و شبکههای پیچیده آسانتر میکند.
در این کد لبه، شما بر اساس برنامه ردیاب خواب از کد لبه قبلی ایجاد می کنید. روش مؤثرتری برای بهروزرسانی فهرست دادههای خواب را یاد میگیرید و نحوه استفاده از اتصال داده با RecyclerView
را یاد میگیرید. (اگر اپلیکیشن نسخه کد قبلی را ندارید، می توانید کد شروع را برای این کد لبه دانلود کنید.)
آنچه از قبل باید بدانید
- ساخت یک رابط کاربری اولیه با استفاده از یک فعالیت، قطعات و نماها.
- پیمایش بین قطعات و استفاده از
safeArgs
برای انتقال داده ها بین قطعات. - مشاهده مدلها، مشاهده کارخانههای مدل، تبدیلها، و
LiveData
و ناظران آنها. - چگونه یک پایگاه داده
Room
ایجاد کنیم، یک DAO ایجاد کنیم و موجودیت ها را تعریف کنیم. - نحوه استفاده از کوروتین ها برای پایگاه داده و سایر کارهای طولانی مدت.
- نحوه پیاده سازی
RecyclerView
اولیه باAdapter
،ViewHolder
و طرح بندی آیتم.
چیزی که یاد خواهید گرفت
- نحوه استفاده از
DiffUtil
برای به روز رسانی موثر لیست نمایش داده شده توسطRecyclerView
. - نحوه استفاده از data binding با
RecyclerView
. - نحوه استفاده از آداپتورهای اتصال برای تبدیل داده ها
کاری که خواهی کرد
- بر اساس برنامه TrackMySleepQuality از کدهای قبلی در این سری ساخته شده است.
- برای به روز رسانی کارآمد لیست با استفاده از
DiffUtil
،SleepNightAdapter
را به روز کنید. - اجرای اتصال داده برای
RecyclerView
، با استفاده از آداپتورهای اتصال برای تبدیل داده ها.
برنامه ردیاب خواب دارای دو صفحه است که با قطعات نشان داده شده است، همانطور که در شکل زیر نشان داده شده است.
اولین صفحه نمایش داده شده در سمت چپ دارای دکمه هایی برای شروع و توقف ردیابی است. صفحه نمایش برخی از داده های خواب کاربر را نشان می دهد. دکمه Clear تمام داده هایی را که برنامه برای کاربر جمع آوری کرده است برای همیشه حذف می کند. صفحه دوم که در سمت راست نشان داده شده است، برای انتخاب رتبه بندی کیفیت خواب است.
این برنامه برای استفاده از کنترلر رابط کاربری، ViewModel
و LiveData
و پایگاه داده Room
برای تداوم داده های خواب طراحی شده است.
داده های خواب در یک RecyclerView
نمایش داده می شود. در این کد لبه، شما بخش DiffUtil
و data-binding را برای RecyclerView
میسازید. بعد از این کد لبه، برنامه شما دقیقاً یکسان به نظر می رسد، اما کارآمدتر و مقیاس بندی و نگهداری آن آسان تر خواهد بود.
میتوانید به استفاده از برنامه SleepTracker از نسخه کد قبلی ادامه دهید، یا میتوانید برنامه RecyclerViewDiffUtilDataBinding-Starter را از GitHub دانلود کنید.
- در صورت نیاز، برنامه RecyclerViewDiffUtilDataBinding-Starter را از GitHub دانلود کنید و پروژه را در Android Studio باز کنید.
- برنامه را اجرا کنید.
- فایل
SleepNightAdapter.kt
را باز کنید. - کد را بررسی کنید تا با ساختار برنامه آشنا شوید. برای خلاصه ای از استفاده از
RecyclerView
با الگوی آداپتور برای نمایش داده های خواب به کاربر، به نمودار زیر مراجعه کنید.
- از ورودی کاربر، برنامه لیستی از اشیاء
SleepNight
ایجاد می کند. هر شیءSleepNight
نشان دهنده یک شب خواب، مدت زمان و کیفیت آن است. -
SleepNightAdapter
لیست اشیاءSleepNight
را با چیزی تطبیق می دهد کهRecyclerView
می تواند استفاده کند و نمایش دهد. - آداپتور
SleepNightAdapter
ViewHolders
تولید می کند که حاوی نماها، داده ها و اطلاعات متا برای نمای Recycler برای نمایش داده ها است. -
RecyclerView
ازSleepNightAdapter
برای تعیین تعداد آیتم برای نمایش (getItemCount()
) استفاده می کند.RecyclerView
ازonCreateViewHolder()
وonBindViewHolder()
برای اتصال دارندگان view به داده ها برای نمایش استفاده می کند.
متد notifyDataSetChanged() ناکارآمد است
برای اینکه به RecyclerView
بگوییم که یک مورد در لیست تغییر کرده و باید بهروزرسانی شود، کد فعلی notifyDataSetChanged()
را در SleepNightAdapter
، همانطور که در زیر نشان داده شده است.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
با این حال، notifyDataSetChanged()
به RecyclerView
می گوید که کل لیست به طور بالقوه نامعتبر است. در نتیجه، RecyclerView
همه موارد موجود در لیست، از جمله مواردی را که روی صفحه قابل مشاهده نیستند، مجدداً باند می کند و دوباره ترسیم می کند. این خیلی کار غیر ضروری است. برای لیستهای بزرگ یا پیچیده، این فرآیند میتواند به اندازهای طول بکشد که هنگام حرکت کاربر در لیست، نمایشگر سوسو بزند یا دچار لکنت شود.
برای رفع این مشکل، میتوانید به RecyclerView
بگویید دقیقاً چه چیزی تغییر کرده است. سپس RecyclerView
می تواند تنها نماهایی را که روی صفحه تغییر کرده اند به روز کند.
RecyclerView
یک API غنی برای به روز رسانی یک عنصر دارد. میتوانید از notifyItemChanged()
برای اطلاع به RecyclerView
استفاده کنید که یک مورد تغییر کرده است، و میتوانید از توابع مشابه برای مواردی که اضافه، حذف یا منتقل میشوند استفاده کنید. شما می توانید همه این کارها را به صورت دستی انجام دهید، اما این کار بی اهمیت است و ممکن است شامل مقدار زیادی کد باشد.
خوشبختانه، راه بهتری وجود دارد.
DiffUtil کارآمد است و کار سخت را برای شما انجام می دهد
RecyclerView
یک کلاس به نام DiffUtil
دارد که برای محاسبه تفاوت بین دو لیست است. DiffUtil
یک لیست قدیمی و یک لیست جدید را می گیرد و متوجه می شود که چه چیزی متفاوت است. موارد اضافه، حذف یا تغییر یافته را پیدا می کند. سپس از الگوریتمی به نام الگوریتم تفاوت یوجین دبلیو مایرز استفاده می کند تا حداقل تعداد تغییراتی را که باید از لیست قدیمی ایجاد شود تا لیست جدید ایجاد کند، مشخص کند.
هنگامی که DiffUtil
متوجه شد چه چیزی تغییر کرده است، RecyclerView
می تواند از آن اطلاعات برای به روز رسانی فقط مواردی که تغییر، اضافه، حذف یا جابجا شده اند استفاده کند، که بسیار کارآمدتر از انجام مجدد کل لیست است.
در این کار، SleepNightAdapter
را ارتقا می دهید تا از DiffUtil
برای بهینه سازی RecyclerView
برای تغییرات داده ها استفاده کند.
مرحله 1: اجرای SleepNightDiffCallback
به منظور استفاده از عملکرد کلاس DiffUtil
، DiffUtil.ItemCallback
را گسترش دهید.
-
SleepNightAdapter.kt
باز کنید. - در زیر تعریف کامل کلاس برای
SleepNightAdapter
، یک کلاس سطح بالای جدید به نامSleepNightDiffCallback
کهDiffUtil.ItemCallback
را گسترش می دهد.SleepNight
را به عنوان یک پارامتر عمومی ارسال کنید.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
- مکان نما را در نام کلاس
SleepNightDiffCallback
قرار دهید. -
Alt+Enter
فشار دهید (Option+Enter
در Mac) و Implement Members را انتخاب کنید. - در محاوره ای که باز می شود، برای انتخاب
areItemsTheSame()
وareContentsTheSame()
شیفت چپ کلیک کنید، سپس روی OK کلیک کنید.
همانطور که در زیر نشان داده شده است، این کار در داخل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
لیست را برای شما پیگیری می کند و هنگامی که لیست به روز شد به آداپتور اطلاع می دهد.
مرحله 1: آداپتور خود را برای گسترش 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()
را حذف کنید، زیراListAdapter
این روش را برای شما پیاده سازی می کند. - برای خلاص شدن از شر خطای
onBindViewHolder()
متغیرitem
را تغییر دهید. به جای استفاده ازdata
برای دریافت یکitem
،getItem(position)
کهListAdapter
ارائه می دهد فراخوانی کنید.
val item = getItem(position)
مرحله 2: از 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)
}
})
- برنامه خود را اجرا کنید سریعتر اجرا میشود، شاید اگر لیست شما کوچک باشد بهطور محسوسی کار نمیکند.
در این کار، از همان تکنیکی که در codelab های قبلی وجود داشت برای تنظیم اتصال داده ها استفاده می کنید و تماس های findViewById()
را حذف می کنید.
مرحله 1: پیوند داده را به فایل طرح بندی اضافه کنید
- فایل طرح بندی
list_item_sleep_night.xml
را در تب Text باز کنید. - مکان نما را روی تگ
ConstraintLayout
قرار دهید وAlt+Enter
را فشار دهید (Option+Enter
در مک). منوی قصد (منوی "رفع سریع") باز می شود. - Convert to data binding layout را انتخاب کنید. این طرح را در
<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 را انتخاب کنید. (اگر همچنان مشکل دارید، File > Invalidate Caches / Restart را انتخاب کنید.) شیء اتصالListItemSleepNightBinding
به همراه کدهای مرتبط به فایل های تولید شده پروژه اضافه می شود.
مرحله 2: طرح بندی مورد را با استفاده از اتصال داده باد کنید
-
SleepNightAdapter.kt
باز کنید. - در کلاس
ViewHolder
متدfrom()
را پیدا کنید. - اعلان متغیر
view
را حذف کنید.
کد برای حذف :
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
- در جایی که متغیر
view
بود، یک متغیر جدید به نامbinding
تعریف کنید که شیء اتصالListItemSleepNightBinding
را مانند شکل زیر باد می کند. وارد کردن لازم شیء binding را انجام دهید.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
- در پایان تابع، به جای برگرداندن
view
،binding
را برگردانید.
return ViewHolder(binding)
- برای خلاص شدن از خطا، مکان نما را روی کلمه
binding
قرار دهید.Alt+Enter
(Option+Enter
در مک) را فشار دهید تا منوی قصد باز شود.
- تغییر پارامتر «itemView» نوع سازنده اصلی کلاس «ViewHolder» به «ListItemSleepNightBinding» را انتخاب کنید . این نوع پارامتر کلاس
ViewHolder
را به روز می کند.
- برای مشاهده تغییر در امضا، به سمت تعریف کلاس
ViewHolder
. شما یک خطا برایitemView
می بینید، زیراitemView
را در متدfrom()
بهbinding
تغییر داده اید.
در تعریف کلاسViewHolder
، روی یکی از مواردitemView
کلیک راست کرده و Refactor > Rename را انتخاب کنید. نام را بهbinding
تغییر دهید. - پیشوند
binding
پارامتر سازنده را باval
قرار دهید تا به یک ویژگی تبدیل شود. - در فراخوانی کلاس والد،
RecyclerView.ViewHolder
، پارامتر را ازbinding
بهbinding.root
تغییر دهید. شما باید یکView
را ارسال کنید وbinding.root
ریشهConstraintLayout
در طرح بندی آیتم شما است. - اعلان کلاس تمام شده شما باید مانند کد زیر باشد.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
همچنین یک خطا برای فراخوانی findViewById()
می بینید و بعداً این مشکل را برطرف می کنید.
مرحله 3: جایگزین findViewById()
اکنون میتوانید sleepLength
، quality
و qualityImage
را بهروزرسانی کنید تا از شی binding
به جای findViewById()
استفاده کنید.
- مقداردهی اولیه
sleepLength
،qualityString
، وqualityImage
را برای استفاده از نماهای شیbinding
، همانطور که در زیر نشان داده شده است، تغییر دهید. پس از این، کد شما نباید دیگر خطا نشان دهد.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
با قرار دادن شی binding، دیگر نیازی به تعریف sleepLength
، quality
و qualityImage
. DataBinding
جستجوها را کش می کند، بنابراین نیازی به اعلام این ویژگی ها نیست.
- روی نام
sleepLength
،quality
وqualityImage
کلیک راست کنید. Refactor > Inline را انتخاب کنید یاControl+Command+N
را فشار دهید (Option+Command+N
در Mac). - برنامه خود را اجرا کنید (ممکن است نیاز داشته باشید که پروژه خود را پاکسازی و بازسازی کنید اگر دارای خطا باشد.)
در این کار، برنامه خود را ارتقا می دهید تا از اتصال داده با آداپتورهای اتصال برای تنظیم داده ها در نماهای خود استفاده کند.
در یک کد لبه قبلی، از کلاس Transformations
برای گرفتن LiveData
و تولید رشته های قالب بندی شده برای نمایش در نمای متن استفاده می کردید. با این حال، اگر نیاز به اتصال انواع مختلف یا انواع پیچیده دارید، میتوانید آداپتورهای اتصال را برای کمک به اتصال دادهها در استفاده از آن انواع ارائه کنید. آداپتورهای صحافی، آداپتورهایی هستند که دادههای شما را میگیرند و آنها را با چیزی تطبیق میدهند که با اتصال داده میتواند برای پیوند دادن یک نما، مانند متن یا تصویر، استفاده کند.
شما قرار است سه آداپتور صحافی را پیاده سازی کنید، یکی برای تصویر با کیفیت و یکی برای هر فیلد متنی. به طور خلاصه، برای اعلام یک آداپتور binding، روشی را تعریف میکنید که یک آیتم و یک view را میگیرد و آن را با @BindingAdapter
. در بدنه روش، تبدیل را اجرا می کنید. در Kotlin، میتوانید یک آداپتور binding را به عنوان یک تابع افزونه روی کلاس view که دادهها را دریافت میکند، بنویسید.
مرحله 1: آداپتورهای اتصال ایجاد کنید
توجه داشته باشید که در مرحله باید تعدادی کلاس وارد کنید و به صورت جداگانه فراخوانی نمی شود.
-
SleepNightAdapater.kt
باز کنید. - در داخل کلاس
ViewHolder
، متدbind()
را پیدا کنید و به خودتان یادآوری کنید که این متد چه کاری انجام می دهد. کدی را که مقادیرbinding.sleepLength
،binding.quality
وbinding.qualityImage
را محاسبه می کند، دریافت کرده و به جای آن در آداپتور استفاده کنید. (در حال حاضر، کد را همانطور که هست بگذارید؛ در مرحله بعد آن را منتقل می کنید.) - در بسته
sleeptracker
، فایلی به نامBindingUtils.kt
ایجاد و باز کنید. - یک تابع افزونه در
TextView
به نامsetSleepDurationFormatted
و در یکSleepNight
عبور دهید. این تابع آداپتور شما برای محاسبه و قالب بندی مدت زمان خواب خواهد بود.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
- در بدنه
setSleepDurationFormatted
، داده ها را به view متصل کنید، همانطور که درViewHolder.bind()
انجام دادید.convertDurationToFormatted()
را فراخوانی کنید و سپسtext
TextView
را روی متن فرمت شده تنظیم کنید. (از آنجایی که این یک تابع پسوندی درTextView
است، می توانید مستقیماً به ویژگیtext
دسترسی داشته باشید.)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
- برای اطلاع از اتصال داده ها در مورد این آداپتور اتصال، تابع را با
@BindingAdapter
حاشیه نویسی کنید. - این تابع آداپتور ویژگی
sleepDurationFormatted
است، بنابراینsleepDurationFormatted
را به عنوان آرگومان به@BindingAdapter
کنید.
@BindingAdapter("sleepDurationFormatted")
- آداپتور دوم کیفیت خواب را بر اساس مقدار موجود در یک شی
SleepNight
می کند. یک تابع افزونه به نامsetSleepQualityString()
درTextView
ایجاد کنید و در یکSleepNight
کنید. - در بدنه، دادهها را مانند
ViewHolder.bind()
به view متصل کنید.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) {
}
- Inside
bind()
، خواب را بهitem
اختصاص دهید، زیرا باید به شی binding در موردSleepNight
جدید خود بگویید.
binding.sleep = item
- در زیر آن خط،
binding.executePendingBindings()
را اضافه کنید. این فراخوانی یک بهینهسازی است که از binding دادهها میخواهد تا هر اتصال معلق را فوراً اجرا کند. هنگامی که از آداپتورهای binding درRecyclerView
استفاده می کنید، همیشه ایده خوبی است کهexecutePendingBindings()
را فراخوانی کنید، زیرا می تواند اندازه نماها را کمی افزایش دهد.
binding.executePendingBindings()
مرحله 3: پیوندها را به طرح XML اضافه کنید
-
list_item_sleep_night.xml
باز کنید. - در
ImageView
، یک ویژگیapp
با همان نام آداپتور اتصال که تصویر را تنظیم می کند، اضافه کنید. همانطور که در زیر نشان داده شده است، متغیرsleep
را پاس کنید.
این ویژگی از طریق آداپتور، ارتباط بین view و شی binding را ایجاد می کند. هر زمان که بهsleepImage
ارجاع داده شود، آداپتور داده هایSleepNight
را تطبیق می دهد.
app:sleepImage="@{sleep}"
- همین کار را برای نمای متن
sleep_length
وquality_string
دهید. هر زمانsleepDurationFormatted
یاsleepQualityString
ارجاع داده شود، آداپتورها دادههایSleepNight
را تطبیق میدهند.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
- برنامه خود را اجرا کنید دقیقاً مانند قبل عمل می کند. آداپتورهای صحافی تمام کارهای قالببندی و بهروزرسانی نماها را با تغییر دادهها انجام میدهند،
ViewHolder
را ساده میکنند و به کد ساختار بسیار بهتری نسبت به قبل میدهند.
شما همان لیست را برای چند تمرین آخر نمایش داده اید. این از طریق طراحی است، تا به شما نشان دهد که رابط Adapter
به شما امکان می دهد کد خود را به روش های مختلف معماری کنید. هرچه کد شما پیچیدهتر باشد، معماری خوب آن اهمیت بیشتری پیدا میکند. در برنامههای تولیدی، این الگوها و سایر الگوها با RecyclerView
استفاده میشوند. الگوها همه کار می کنند و هر کدام مزایای خود را دارند. کدام یک را انتخاب می کنید بستگی به چیزی دارد که می سازید.
تبریک میگم در این مرحله شما به خوبی در راه تسلط بر RecyclerView
در اندروید هستید.
پروژه Android Studio: RecyclerViewDiffUtilDataBinding .
DiffUtil
:
-
RecyclerView
یک کلاس به نامDiffUtil
دارد که برای محاسبه تفاوت بین دو لیست است. -
DiffUtil
کلاسی به نامItemCallBack
که شما آن را گسترش می دهید تا تفاوت بین دو لیست را بفهمید. - در کلاس
ItemCallback
، بایدareItemsTheSame()
وareContentsTheSame()
را لغو کنید.
ListAdapter
:
- برای دریافت مدیریت لیست به صورت رایگان، می توانید از کلاس
ListAdapter
به جایRecyclerView.Adapter
استفاده کنید. با این حال، اگر ازListAdapter
استفاده میکنید، باید آداپتور خود را برای طرحبندیهای دیگر بنویسید، به همین دلیل است که این کد لبه به شما نشان میدهد که چگونه این کار را انجام دهید. - برای باز کردن منوی قصد در Android Studio، مکان نما را روی هر کدی از کد قرار دهید و
Alt+Enter
(Option+Enter
در مک) را فشار دهید. این منو به ویژه برای بازآفرینی کد و ایجاد خرد برای پیاده سازی روش ها مفید است. منو به زمینه حساس است، بنابراین برای دریافت منوی صحیح باید مکان نما را دقیقاً قرار دهید.
اتصال داده ها:
- برای اتصال داده ها به نماها، از اتصال داده در طرح بندی مورد استفاده کنید.
آداپتورهای اتصال:
- شما قبلاً از
Transformations
برای ایجاد رشته ها از داده ها استفاده کرده اید. اگر نیاز به اتصال دادهها از انواع مختلف یا پیچیده دارید، آداپتورهای اتصال را برای کمک به اتصال دادهها در استفاده از آنها فراهم کنید. - برای اعلام یک آداپتور binding، متدی را تعریف کنید که یک آیتم و یک view را می گیرد و روی روش را با
@BindingAdapter
حاشیه نویسی کنید. در Kotlin، می توانید آداپتور binding را به عنوان یک تابع افزونه درView
بنویسید. به نام ویژگی که آداپتور تطبیق می دهد، عبور دهید. مثلا:
@BindingAdapter("sleepDurationFormatted")
- در طرح XML، یک ویژگی
app
را با همان نام آداپتور binding تنظیم کنید. یک متغیر را با داده ارسال کنید. مثلا:
.app:sleepDurationFormatted="@{sleep}"
دوره های بی ادبی:
مستندات توسعه دهنده اندروید:
- یک لیست با RecyclerView ایجاد کنید
-
RecyclerView
-
DiffUtil
- کتابخانه صحافی داده
- آداپتورهای صحافی
-
notifyDataSetChanged()
-
Transformations
سایر منابع:
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را درجه بندی کنید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است به آنها اختصاص دهند.
اگر به تنهایی بر روی این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
یه این سوالات پاسخ دهید
سوال 1
کدام یک از موارد زیر برای استفاده از DiffUtil
؟ همه موارد اعمال شده را انتخاب کنید.
ItemCallBack
کلاس ItemCallBack را گسترش دهید.
▢ areItemsTheSame()
را لغو کنید.
▢ areContentsTheSame()
را لغو کنید.
▢ برای ردیابی تفاوت بین موارد از اتصال داده استفاده کنید.
سوال 2
کدام یک از موارد زیر در مورد آداپتورهای اتصال درست است؟
▢ آداپتور binding تابعی است که با @BindingAdapter
مشروح شده است.
▢ استفاده از یک آداپتور صحافی به شما امکان می دهد قالب بندی داده ها را از نگهدارنده نمایش جدا کنید.
▢ اگر میخواهید از آداپتورهای اتصال استفاده کنید، باید از RecyclerViewAdapter
استفاده کنید.
▢ آداپتورهای صحافی راه حل خوبی برای زمانی هستند که نیاز به تبدیل داده های پیچیده دارید.
سوال 3
چه زمانی باید از Transformations
به جای آداپتور اتصال استفاده کنید؟ همه موارد اعمال شده را انتخاب کنید.
▢ داده های شما ساده است.
▢ شما در حال قالب بندی یک رشته هستید.
▢ لیست شما بسیار طولانی است.
▢ ViewHolder
شما فقط دارای یک نمای است.
درس بعدی را شروع کنید: