[Học Android] Hướng dẫn sử dụng MergeAdapter cho RecyclerView trong Android
![[Học Android] Hướng dẫn sử dụng MergeAdapter cho RecyclerView trong Android](https://webnulled.net/wp-content/uploads/2022/02/android-huong-dan-su-dung-mergeadapter-cho-recyclerview-trong-android_6202b222e2003.png)
MergeAdapter là 1 adapter được tích hợp trong recyclerview:1.2.0-alpha0 cho phép bạn kết hợp nhiều adapter trong 1 RecyclerView thay vì sử dụng nhiều 1 adapter với nhiều kiểu item như trước đây. Cùng tìm hiểu cách sử dụng MergeAdapter trong bài viết hôm nay nhé!
1. Dẫn nhập
Giả sử chúng ta nhận được yêu cầu thực hiện một màn hình như sau:
Sẽ có nhiều ý tưởng nảy sinh trong suy nghĩ của chúng ta khi nhìn vào hình trên. Ý tưởng sử dụng một RecyclerView chứa nhiều kiểu view (view type) trong adapt
MergeAdapter là 1 adapter được tích hợp trong recyclerview:1.2.0-alpha0 cho phép bạn kết hợp nhiều adapter trong 1 RecyclerView thay vì sử dụng nhiều 1 adapter với nhiều kiểu item như trước đây. Cùng tìm hiểu cách sử dụng MergeAdapter trong bài viết hôm nay nhé!
Table of Contents
1. Dẫn nhập
Giả sử chúng ta nhận được yêu cầu thực hiện một màn hình như sau:
Sẽ có nhiều ý tưởng nảy sinh trong suy nghĩ của chúng ta khi nhìn vào hình trên. Ý tưởng sử dụng một RecyclerView chứa nhiều kiểu view (view type) trong adapter đương nhiên sẽ là ưu tiên hàng đầu! Tuy nhiên, với ý tưởng này, chúng ta sẽ phải quản lý nhiều kiểu view trong một adapter. Trong màn hình đơn giản ở trên, chúng ra sẽ có 3 kiểu view:
-
Thứ nhất là kiểu chứa tên và mô tả của người dùng.
-
Thứ hai là kiểu chứa thông tin của người dùng (avatar, tên).
-
Thứ ba là một biểu ngữ (banner) thông tin.
Với màn hình trên chúng ta đã phải định nghĩa 3 kiểu view, vậy còn đối với những màn hình phức tạp thì sao? Có khi chúng ta cần phải định nghĩa hàng chục kiểu view. Vậy câu hỏi đặt ra là chúng ta có thể đơn giản hóa việc tập trung tất cả các kiểu view vào một chỗ để xử lý không?
MergeAdapter chính à một giải pháp để giải quyết câu hỏi trên!
2. Sử dụng MergeAdapter
Bước 1:
Đầu tiên chúng ta sẽ sử dụng phiên bản RecyclerView thích hợp (MergeAdapter chỉ hỗ trợ phiên bản RecyclerView mới nhất)
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02"
Sau đó chúng ta sẽ tạo ra 3 model tương ứng với màn hình trên: MyDetail, Banner, User.
data class User(
val id: Int = 0,
val name: String = "",
val avatar: String = ""
)
data class MyDetail(
val id: Int = 0,
val name: String = "",
val aboutMe: String = ""
)
data class Banner(
val bannerImage: Int = 0
)
Bước 2
Tạo data
object DataSource {
fun getUser() = ArrayList().apply {
add(User(1, "Himanshu", "https://s3.amazonaws.com/uifaces/faces/twitter/sunlandictwin/128.jpg"))
add(User(2, "Alford Hoeger", "https://s3.amazonaws.com/uifaces/faces/twitter/mufaddal_mw/128.jpg"))
add(User(3, "Terrance Halvorson", "https://s3.amazonaws.com/uifaces/faces/twitter/mufaddal_mw/128.jpg"))
add(User(3, "Morgan McGlynn", "https://s3.amazonaws.com/uifaces/faces/twitter/allfordesign/128.jpg"))
add(User(4, "Ms. Ramiro DuBuque", "https://s3.amazonaws.com/uifaces/faces/twitter/shaneIxD/128.jpg"))
add(User(5, "Kolby Orn", "https://s3.amazonaws.com/uifaces/faces/twitter/johnsmithagency/128.jpg"))
add(User(6, "Elijah Schoen MD", "https://s3.amazonaws.com/uifaces/faces/twitter/alxndrustinov/128.jpg"))
}
fun getBanner() = Banner(R.drawable.publication_site_cover)
}
Bước 3
MergeAdapter sẽ gom nhóm và sắp xếp các adapter của RecyclerView theo trình tự do đó chúng ta sẽ tạo ra 3 adapter và UI item khác nhau:
MyDetailAdapter
class MyDetailAdapter(
private val myDetail: MyDetail
) : RecyclerView.Adapter() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(user: MyDetail) {
itemView.textViewUser.text = user.name
itemView.textViewAboutMe.text = user.aboutMe
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_layout_my_detail, parent,
false
)
)
override fun getItemCount(): Int = 1
override fun onBindViewHolder(holder: DataViewHolder, position: Int) =
holder.bind(myDetail)
}
item_layout_my_detail
UsersAdapter
class UsersAdapter(
private val users: ArrayList
) : RecyclerView.Adapter() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
itemView.textViewUserName.text = user.name
Glide.with(itemView.imageViewAvatar.context)
.load(user.avatar)
.into(itemView.imageViewAvatar)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_layout, parent,
false
)
)
override fun getItemCount(): Int = users.size
override fun onBindViewHolder(holder: DataViewHolder, position: Int) =
holder.bind(users[position])
}
item_layout
BannerAdapter
class BannerAdapter(
private val banner: Banner
) : RecyclerView.Adapter() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(banner: Banner) {
Glide.with(itemView.imageViewBanner.context)
.load(user.bannerImage)
.into(itemView.imageViewBanner)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_layout_banner, parent,
false
)
)
override fun getItemCount(): Int = 1
override fun onBindViewHolder(holder: DataViewHolder, position: Int) =
holder.bind(banner)
}
item_layout_banner
Bước 4
Chúng ta sẽ khai báo các adapter lần lượt như sau:
lateinit var adapter: MergeAdapter
lateinit var myDetailAdapter: MyDetailAdapter
lateinit var userVerticalAdapter: UsersAdapter
lateinit var bannerAdapter: BannerAdapter
Tạo một biến chứa thông tin:
val myDetail = MyDetail(1, "Himanshu Singh", "I am an writer and Open Source contributor in MindOrks.")
Tạo 1 hàm để khởi tạo và set vào adapter:
private fun setupDataInRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(this)
userVerticalAdapter = UsersAdapter(DataSource.getUser())
bannerAdapter = BannerAdapter(DataSource.getBanner())
myDetailAdapter = MyDetailAdapter(myDetail)
adapter = MergeAdapter(myDetailAdapter, userVerticalAdapter,bannerAdapter)
recyclerView.adapter = adapter
}
Chú ý: MergeAdapter sẽ hiển thị danh sách dữ liệu theo thứ tự mà chúng ta thêm vào.
3. Lưu ý khi sử sụng MergeAdapter
Các điểm cần ghi nhớ
- Nếu chúng ta muốn sử dụng nhiều lần cùng một adapter trong RecyclerView thì có thể tạo ra nhiều instance của adapter đó và thêm vào constructor của MergeAdapter.
- Chúng ta nên xử lý logic riêng biệt trong từng adapter.
- Khi chúng ta cập nhật data trong bất kỳ adapter con nào bằng cách gọi notifyDataSetChanged() thì MergeAdapter cũng sẽ gọi notifyDataSetChanged().
- Thay vì thêm từng adapter riêng lẻ thì chúng ta có thể thêm một danh sách các adapter trong constructor của MergeAdapter.
val listOfAdapters = listOf
>(myDetailAdapter, userVerticalAdapter, bannerAdapter) adapter = MergeAdapter(listOfAdapters)
Các điểm cần lưu ý
- Trong trường hợp chúng ta muốn tái sử dụng ViewHolder cho nhiều adapter thì cần phải set giá trị của isolateViewTypes là false– –
val configBuilder = MergeAdapter.Config.Builder()
configBuilder.setIsolateViewTypes(false)
val adapter = MergeAdapter(configBuilder.build(),myDetailAdapter, userVerticalAdapter, bannerAdapter)
- Trong trường hợp chúng ta không muốn thêm adapter trực tiếp trong constructor của MergeAdapter làm như sau:
val adapter = MergeAdapter(listOfAdapters)
adapter.addAdapter(bannerAdapter)
Adapter mới sẽ nằm cuối cùng của list adapter. Nếu như muốn add tại một vị trí bất kỳ thì chúng ta sẽ làm như sau:
adapter.addAdapter(position,bannerAdapter) – position: vị trí trong list adapter
- Để xóa adapter chúng ta gọi:
adapter.removeAdapter(adapter)
- Để biết tổng số item của tất cả adapter trong RecyclerView chúng ta dùng
adapter.itemCount
- Để lấy danh sách adapter đang tồn tại trong MergeAdapter, chúng ta dùng
adapter.adapters
4. Kết luận
Hy vọng với bài viết này các bạn sẽ có thêm sự lựa chọn khi làm việc với RecyclerView có nhiều kiểu item.
Cảm ơn các bạn đã đọc bài viết.
Chào thân ái và quyết thắng!
Theo viblo.asia