Google的MergeAdapter的使用

5,078 阅读2分钟

1. 简介

这次想要介绍的是由谷歌推出的MergeAdapter。听名字就应该知道它是和RecyclerView相关的组件。

该组件是在androidx.recyclerview:recyclerview:1.2.0-alpha02中推出,它的主要中作用是把多个Adapter集中在一个Adapter中,然后在RecyclerView中显示。

所以如果想实现RecyclerView中显示不同的ViewType就需要利用RecyclerViewgetItemViewType,或者使用类似于Groupie(关于Groupie的教程)的外部库。

但是有了MergeAdapter, 我们可以直接使用它就可以实现上述的需求,非常的方便,而且足够优雅。

废话不多说,先介绍用法,然后再讨论它的好与不足。

2. 使用方法

2.1 引入库

build.gradle中加入RecyclerView的库。

androidx.recyclerview:recyclerview:1.2.0-alpha02

2.2 创建Adapter的Layout

这里根据自己的需求创建layout,需要多少ViewType就创建相应的layout就可以了。

<?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>

2.3 创建Adapter

这里也是根据自己的需求创建Adapter就可以了。和正常的用法一样。

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)

2.4 创建MergeAdapter

我们在MainActivity中创建MergeAdapter然后传RecyclerView

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

3. 关于MergeAdapter

3.1 移除adapter

可以对已经存在的adapter进行移除。

mergeAdapter.removeAdapter(firstAdapter)

3.2 添加adapter

可以在MergeAdapter传给RecyclerView以后,还以可以添加adapter。

mergeAdapter.addAdapter(firstAdapter)

3.3 获取当前的adapter数组

可以获取当前已经传给RecyclerView的adapter数组。

val adapters = mergeAdapter.adapters

3.4 adapter的复用

默认的情况是每个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))

3.5 数据更新的通知

需要有新数据更新时调用相应的adapter, 然后用相应的adapternotifyDatasetChanged。调用adapternotifyDatasetChanged,最后MergeAdapternotifyDatasetChanged也会被调用。

thirdAdapter.submitList(addData())
thirdAdapter.notifyDataSetChanged()

4. 不足之处

有点自然不必多说,但是MergeAdapter有一个显而易见的不足之处就是ViewType不能混合使用,使其应用范围受到了很大的限制。但是如果没有这样的需求则还是优先使用MergeAdapter吧!

5. GitHub

GitHub: github.com/HyejeanMOON…

Android ConstraintLayout的易懂教程: juejin.cn/post/684490…

关于Jetpack的Paging教程: juejin.cn/post/684490…

Groupie的教程: juejin.cn/post/684490…