استفاده از دیتا بایندینگ در ریسایکلرویو (اندروید)
سلام این اولین پست من هست امیدوارم خوشتون بیاد و بتونید ازش استفاده کنید.
خب دیتابایندینگ چه مشکلی رو برای ما حل کرده؟ قبل از به وجود اومدن دیتابایندینگ ما مجبور بودیم تک تک ویو هایی که داشتیم(مثل تکستویو و ادیتتکست) با استفاده از findViewById به کد جاوا متصل کنیم(البته اگه از زبان کاتلین برای توسعه اپ استفاده کنید دیگه مجبور نیستید از findViewById استفاده کنید) و بعد از اون دیتای هر ویو رو داخلش بریزیم برای نمونه مثال زیر رو در نظر بگیرید:
TextView tvFirstName = findViewById(R.id.first_name);
TextView tvLastName = findViewById(R.id.last_name);
TextView tvAge = findViewById(R.id.age);
TextView tvDescription = findViewById(R.id.description);
tvFirstName.setText("Mohammad");
tvLastName.setText("Jahangiri");
tvAge.setText("23");
tvDescription.setText("Description");
همونطور که بالاتر توضیح دادیم اول ویوبایندینگ(findViewById) کردیم بعد دیتابایندینگ(setText)
شاید این کار برای چهار ویو خیلی آسون باشه اما وقتی تعداد ویو ها بیشتر بشه باید این کار تکراری رو برای هر ویو انجام بدید، اینجاست که دیتابایندینگ به کمک ما میاد و ما رو از شر boilerplate های کسالت آور رها میکنه.
اگر بای دیتابایندینگ آشنایی ندارید تو مقاله زیر میتونید مراحل کامل نحوه پیاده سازی دیتابایندینگ رو به زبان ساده مطالعه کنید.
تو مقاله بالا یاد گرفتید که چطور میشه دیتابایندینگ رو فعال و از اون استفاده کنید، اما موضوع نوشته ما پیاده سازی دیتا بایندینگ تو ریسایکلرویو هست که آموزشش توی مقاله مذکور نبود.
اول برای آیتم های ریسایکلرویو نیاز به یک دیتا مدل داریم، دیتا مدل زیر شامل سه خصوصیت (name, description, isFavorite) میشه:
data class Person(
var name: String,
var description: String,
var isFavorite: Boolean
)
همونطور که میدونید به یک لایه برای آیتم ها نیاز داریم، طراحی لایه هم به صورت زیر هست:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="person"
type="com.github.masterj3y.Person" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/nameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/favorite"
android:text="@{person.name}"
android:textColor="#000"
android:textSize="20sp"
tools:text="Title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/nameTextView"
android:layout_alignStart="@id/nameTextView"
android:text="@{person.description}"
tools:text="Description" />
<ImageView
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:src="@drawable/ic_turned_in_black_24dp"
android:visibility="@{person.isFavorite?View.VISIBLE:View.INVISIBLE}" />
</RelativeLayout>
</layout>
بعد از ایجاد لایه بالا یک بار پروژه رو Rebuild کنید تا کدهای بایندینگ برای ما Generate بشن، برای این کار از منوی Build گزینه Rebuild Project رو انتخاب کنید.
وقتی که پروژه بیلد شد کلاسی تحت عنوان PersonsAdapter ایجاد کنید
اگر آداپتر های ریسایکلرویو رو بدون استفاده از دیتابایندینگ پیادهمیکردیم باید یک پارامتر رو به عنوان itemView به کلاس پدر یا همون RecyclerView.ViewHolder پاس میدادیم دقیقا مثل کد زیر:
inner class PersonViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
}
طبق معمول باید توی ViewHolder هم تک تک ویو ها رو با استفاده از findViewById باندشون کنیم، ولی به لطف DataBinding دیگه نیازی به این بویلرپلیت ها نداریم کافیه به جای itemView تو کانستراکتور PersonViewHolder یه نمونه از نوع کلاس بایندینگ ایجاد شده بهش بدیم، خب کلاس بایندینگ ایجاد شده چی هست؟ همون کدهایی که بعد از بیلد کردن برامون Generate شدن، این کد ها برای هر لایه تو یک کلاس هم اسم همون لایه ایجاد میشه، برای مثال اگر اسم لایه مربوط به آیتم های ریسایکلرویویی که کد xml ش رو بالاتر گذاشتم list_person_item_layout.xml باشه کلاسی که اندروید استودیو برای DataBinding این لایه برای ما تولید میکنه ListPersonItemLayoutBinding خواهد بود (دقت کنید همه _ ها حذف شد و اسم به صورت CamelCase نوشته شد)
حالا کافیه به جای itemView ما یک نمونه از ListPersonItemLayoutBinding تو کانستراکتور PersonViewHolder داشته باشیم:
inner class PersonViewHolder(privateval binder: ListPersonItemLayoutBinding) :
RecyclerView.ViewHolder(binder.root) {
}
کلاس RecyclerView.ViewHolder یک ویو رو به عنوان پارامتر کانستراکتور میگیره ما هم مقدار binder.root بهش پاس میدیم
و حالا برای آخرین مرحله کافیه یک شی از کلاس Person به binder بدیم تا DataBinding ویو ها رو به صورت اتوماتیک بایند و دیتای هر ویو رو ست کنه، کد زیر همین کار رو برای ما انجام میده:
inner class PersonViewHolder(privateval binder: ListPersonItemLayoutBinding) :
RecyclerView.ViewHolder(binder.root) {
fun render(person: Person) {
binder.person = person
}
}
بله دیگه نیازی به findViewById و بقیه بویلرپلیت ها نیست، کد ویوهولدر ما فقط شامل همین چند خط میشه و تمام، کد کامل PersonsAdapter هم به صورت زیر هست:
class PersonsAdapter(privateval personsList: List<Person>) :
RecyclerView.Adapter<PersonsAdapter.PersonViewHolder>() {
private lateinit var context: Context
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
context = recyclerView.context
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = PersonViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.list_person_item_layout,
parent,
false
)
)
override fun getItemCount() = personsList.size
override fun onBindViewHolder(holder: PersonViewHolder, position: Int) =
holder.render(personsList[position])
inner class PersonViewHolder(privateval binder: ListPersonItemLayoutBinding) :
RecyclerView.ViewHolder(binder.root) {
fun render(person: Person) {
binder.person = person
}
}
}
کد کامل پروژه رو هم تو گیت هاب گذاشتم:
برای اولین نوشته من میتونه خیلی اشکالات داشته باشه، اگر خیلی سخت بود یا متوجه مورد اشتباهی یا غلط املایی شدین ممنون میشم توی کامنت ها مطلعم کنید:) ممنونم که وقتتون رو در اختیار من گذاشتین.
مطلبی دیگر از این انتشارات
فلاتر بهتر است یا کاتلین ؟ آیا مقایسه این دو صحیح است ؟ قسمت ۱
مطلبی دیگر از این انتشارات
استفاده از Dagger Hilt به صورت پروژه محور (قسمت دوم)
مطلبی دیگر از این انتشارات
اپ من , روشنا را رایگان در مارکت های ایرانی ببینید! (آپدیت)