此次想要介紹的是由谷歌推出的MergeAdapter
。聽名字就應該知道它是和RecyclerView
相關的組件。android
該組件是在androidx.recyclerview:recyclerview:1.2.0-alpha02
中推出,它的主要中做用是把多個Adapter
集中在一個Adapter
中,而後在RecyclerView
中顯示。git
正常的Adapter
是隻能存在一種ViewType
,因此若是想實現RecyclerView
中顯示不一樣的ViewType
則須要本身額外進行擴展,或者使用相似於Groupie
(關於Groupie的教程)的外部庫。github
可是有了MergeAdapter
, 咱們能夠直接使用它就能夠實現上述的需求,很是的方便。數組
廢話很少說,先介紹用法,而後再討論它的好與不足。app
在build.gradle
中加入RecyclerView
的庫。ide
androidx.recyclerview:recyclerview:1.2.0-alpha02
複製代碼
這裏根據本身的需求建立layout,須要多少ViewType
就建立相應的layout就能夠了。post
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="20sp"
android:layout_marginStart="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="hello" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
複製代碼
這裏也是根據本身的需求建立Adapter就能夠了。和正常的用法同樣。gradle
class FirstAdapter(private val data: List<String>) :
ListAdapter<String, FirstAdapter.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from((parent.context))
val binding: ItemFirstBinding =
DataBindingUtil.inflate(inflater, R.layout.item_first, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.textView1.text = data[position]
}
override fun getItemCount(): Int {
return data.size
}
class DiffCallback : DiffUtil.ItemCallback<String>() {
override fun areContentsTheSame(oldItem: String, newItem: String): Boolean {
return oldItem == newItem
}
override fun areItemsTheSame(oldItem: String, newItem: String): Boolean {
return oldItem === newItem
}
}
class ViewHolder(var binding: ItemFirstBinding) : RecyclerView.ViewHolder(binding.root)
複製代碼
咱們在MainActivity中建立MergeAdapter
而後傳RecyclerView
。ui
val firstAdapter = FirstAdapter(data)
val secondAdapter = SecondAdapter(data)
val thirdAdapter = ThirdAdapter(data)
// 建立MergeAdapter
// 須要經過listOf把多個adapter傳給MergeAdapter
mergeAdapter = MergeAdapter(listOf(firstAdapter,secondAdapter,thirdAdapter))
binding.recyclerView.adapter = mergeAdapter
複製代碼
能夠對已經存在的adapter進行移除。spa
mergeAdapter.removeAdapter(firstAdapter)
複製代碼
能夠在MergeAdapter
傳給RecyclerView
之後,還以能夠添加adapter。
mergeAdapter.addAdapter(firstAdapter)
複製代碼
能夠獲取當前已經傳給RecyclerView
的adapter數組。
val adapters = mergeAdapter.adapters
複製代碼
默認的狀況是每一個adapter
都會維護本身的ViewHolder pool
,且adapter
之間不能複用。若是咱們想要複用則須要設置MergeAdapter.Config
。
val configBuilder = MergeAdapter.Config.Builder()
configBuilder.setIsolateViewTypes(false)
複製代碼
而後在建立MergeAdapter
的時候,把Config
傳進去。
val mergeAdapter = MergeAdapter(configBuilder.build(),listOf(firstAdapter,secondAdapter,thirdAdapter))
複製代碼
須要有新數據更新時調用相應的adapter
, 而後用相應的adapter
的notifyDatasetChanged
。調用adapter
的notifyDatasetChanged
,最後MergeAdapter
的notifyDatasetChanged
也會被調用。
thirdAdapter.submitList(addData())
thirdAdapter.notifyDataSetChanged()
複製代碼
有點天然沒必要多說,可是MergeAdapter
有一個顯而易見的不足之處就是ViewType
不能混合使用,使其應用範圍受到了很大的限制。可是若是沒有這樣的需求則仍是優先使用MergeAdapter
吧!
GitHub: github.com/HyejeanMOON…
關於Jetpack的Paging教程: juejin.im/post/5e75db…
Groupie的教程: juejin.im/post/5e9059…