使用 DataBinding 的 RecyclerView

这是一个通用的 ViewHolder 类,可以与任何 DataBinding 布局一起使用。这里使用膨胀的 View 对象和 DataBindingUtil 实用程序类创建特定 ViewDataBinding 类的实例。

import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class BindingViewHolder<T> extends RecyclerView.ViewHolder{

    private final T binding;

    public BindingViewHolder(View itemView) {
        super(itemView);
        binding = (T)DataBindingUtil.bind(itemView);
    }

    public T getBinding() {
        return binding;
    }
}

创建此类后,你可以在布局文件中使用 <layout> 为该布局启用数据绑定,如下所示:

file name: my_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="item"
            type="ItemModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@{item.itemLabel}" />
    </LinearLayout>
</layout>

这是你的示例 dataModel:

public class ItemModel {
    public String itemLabel;
}

默认情况下,Android 数据绑定库根据布局文件名生成 ViewDataBinding 类,将其转换为 Pascal 大小写,并为其添加后缀 Binding。对于这个例子,布局文件 my_item.xml 将是 MyItemBinding。Binding 类还有一个 setter 方法来设置在布局文件中定义为数据的对象(本例中为 ItemModel)。

现在我们已经完成了所有的工作,我们可以像这样实现我们的适配器

class MyAdapter extends RecyclerView.Adapter<BindingViewHolder<MyItemBinding>>{
    ArrayList<ItemModel> items = new ArrayList<>();
        
    public MyAdapter(ArrayList<ItemModel> items) {
        this.items = items;
    }

    @Override public BindingViewHolder<MyItemBinding> onCreateViewHolder(ViewGroup parent, int viewType) {
        return new BindingViewHolder<>(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item, parent, false));
    }

    @Override public void onBindViewHolder(BindingViewHolder<ItemModel> holder, int position) {
        holder.getBinding().setItemModel(items.get(position));
        holder.getBinding().executePendingBindings();
    }

    @Override public int getItemCount() {
        return items.size();
    }
}