天天看點

【Android】分享一個在RecyclerView中使用資料綁定(DataBinding)的Adapter基類一、BaseDataBindingAdapter代碼二、示例

文章目錄

  • 一、BaseDataBindingAdapter代碼
  • 二、示例
    • 實作效果:
    • 示例代碼
      • 1. 布局
      • 2. 類代碼

BaseDataBindingAdapter是一個簡易的、在RecyclerView中使用資料綁定、隻支援一種資料類型和布局的Recycler Adapter基類,适用于單一資料、布局類型的簡單RecyclerView。

使用BaseDataBindingAdapter,實作一個簡易的、使用資料綁定的Recycler Adapter,隻需要極少量的代碼。BaseDataBindingAdapter的實作非常簡單,這在其使用便捷的同時,也導緻了不适用于多布局類型的RecyclerView。

一、BaseDataBindingAdapter代碼

/**
 * 加入了DataBinding的RecyclerView.Adapter基類,在RecyclerView中實作了DataBinding,适合簡單清單。
 * 隻支援綁定一種資料類型,重寫[layoutId]設定布局,重寫[onBindViewHolder]抽象函數實作資料綁定。
 *
 * 其中[T]是資料類型,在xml中使用;[B]是對應布局的資料綁定類。
 *
 * 實作類隻需要重寫布局id[layoutId]和[onBindViewHolder]一個抽象函數即可。
 */
abstract class BaseDataBindingAdapter<T, B : ViewDataBinding> 
	: RecyclerView.Adapter<BaseDataBindingAdapter.ViewHolder>() {
    protected val TAG = javaClass.simpleName // TAG

    /**
     * 資料清單,隻支援一種類型的資料
     */
    protected val data = mutableListOf<T>()
    override fun getItemCount(): Int = data.size

    /**
     * 布局檔案的id,在子類中實作(可以在構造函數中重寫)
     */
    abstract val layoutId: Int

    /**
     * ViewHolder,因為實作資料綁定,是以實際操作由[binding]實作。
     */
    open class ViewHolder(open val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)

    final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = DataBindingUtil.inflate<B>(
            LayoutInflater.from(parent.context), layoutId, parent, false
        )
        return ViewHolder(binding)
    }

    /**
     * 全量更新資料
     */
    fun setData(_data: List<T>?) {
        Log.v(TAG, "setData: $_data")
        data.clear()
        if (!_data.isNullOrEmpty()) data.addAll(_data)
        notifyDataSetChanged()
    }

    final override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        @Suppress("UNCHECKED_CAST")
        onBindViewHolder(holder.binding as B, data[position])
        holder.binding.executePendingBindings()
    }

    /**
     * 顯示資料時使用。通過[binding]設定布局中對應的變量[item]更新資料。
     */
    abstract fun onBindViewHolder(binding: B, item: T)

}
           

二、示例

實作效果:

一個簡單的使用者清單。

【Android】分享一個在RecyclerView中使用資料綁定(DataBinding)的Adapter基類一、BaseDataBindingAdapter代碼二、示例

示例代碼

為了避免示例複雜化,這裡隻在Recycler item中使用了資料綁定作為示範。

1. 布局

Activity布局

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eeeeee"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</merge>
           

Recycler item布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tool="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="top.littlefogcat.ui.databindinginrecyclerview.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:padding="16dp">

        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginEnd="10dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"姓名:"+user.name+",年齡:"+user.age}'
            tool:text="姓名:小波,年齡:18" />
    </LinearLayout>
</layout>
           

2. 類代碼

DatabindingRecyActivity

class DatabindingRecyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_databinding_recy)

        val adapter = UserListAdapter(R.layout.user_item)
        rv.adapter = adapter

        // -------------------------- 加載假資料 -----------------------------
        arrayOf(
            "Alice", "Bob", "Clark", "Diana", "Ella", "Frank", "George", 
            "Holy shit", "Iris", "John", "Ketty", "Laura", "Mark",
            "Nash", "Olive", "Peter", "Quincy", "Rita", "Sandra", "Tony", 
            "Uzi", "Vincent", "Worker", "XBox", "Yuri", "Zoey"
        ).map {
            User(it, Random.Default.nextInt(80))
        }.toMutableList().run {
            adapter.setData(also { shuffle() })
        }
        // ------------------------------------------------------------------
    }
}
           

UserListAdapter

class UserListAdapter(override val layoutId: Int) : BaseDataBindingAdapter<User, UserItemBinding>() {
    override fun onBindViewHolder(binding: UserItemBinding, item: User) {
        binding.user = item
    }
}
           

可以看到,隻需要一行代碼就可以實作一個資料綁定的Recycler Adapter,對于單一少量資料類型的RecyclerView非常好用。