文章目录
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)
}
二、示例
实现效果:
一个简单的用户列表。
示例代码
为了避免示例复杂化,这里只在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非常好用。