RcyclerView DataBinding结合
最近在将自己之前的项目从MVP更改到MVVM,遇到了一些坑,也学习了不少。记录下自己怎么去解决RcyclerView和DataBinding结合的过程。本文的前提是假设你有一部分的MVVM的基础,并且知道如何是用DataBinding。
重点
先说重点,RcyclerView和DataBinding结合最重要的其实就两个方法:
- onCreateViewHolder()中ViewHolder获取了对View的引用,方便快速的处理数据
- onBindViewHolder()中将指定的数据传送给View
实现
为了达到通用的目的,我创建了一个基础的Adapter。按照上面说的两个重要方法。我们看看如何实现:
onCreateViewHolder()
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
B binding = DataBindingUtil.inflate(LayoutInflater.from(this.context), this.getLayoutResId(viewType), parent, false);
return new BaseBindingViewHolder(binding.getRoot());
}
在这个方法中,我们通过DataBinding获取了itemLayout的一个binding对象的引用,同时通过**binding.getRoot()**将View传递给内部ViewHolder类,去构造一个持有View的引用的ViewHolder。
onBindViewHolder()
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
B binding = DataBindingUtil.getBinding(holder.itemView);
binding.getRoot().setTag(items.get(position));
this.onBindItem(binding, this.items.get(position));
}
在这个方法中,通过getBinding()获取binding对象,连同数据一同传递给虚函数onBindItem(),交由上层去完成具体的数据逻辑。setTag()的目的其实是为了在上层实现Listener的时候,方便定位数据。
最后我们来看下,整个BaseAdapter
public abstract class BaseBindingAdapter<M, B extends ViewDataBinding> extends RecyclerView.Adapter {
protected Context context;
protected ObservableArrayList<M> items;
public BaseBindingAdapter(Context context) {
this.context = context;
this.items = new ObservableArrayList<>();
}
public ObservableArrayList<M> getItems() {
return items;
}
public class BaseBindingViewHolder extends RecyclerView.ViewHolder {
public BaseBindingViewHolder(View itemView) {
super(itemView);
}
}
@Override
public int getItemCount() {
return this.items.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
B binding = DataBindingUtil.inflate(LayoutInflater.from(this.context), this.getLayoutResId(viewType), parent, false);
return new BaseBindingViewHolder(binding.getRoot());
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
B binding = DataBindingUtil.getBinding(holder.itemView);
binding.getRoot().setTag(items.get(position));
this.onBindItem(binding, this.items.get(position));
}
protected abstract int getLayoutResId(int viewType);
protected abstract void onBindItem(B binding, M item);
}
实现SimpleDataBindingAdapter
有了上面的基类,实现起来就挺方便了。直接看代码就好了。
public class SimpleDataBindingAdapter extends BaseBindingAdapter<UserBean, ItemMainBinding> implements View.OnClickListener {
private OnRecyclerViewItemClickListener mOnItemClickListener = null;
public interface OnRecyclerViewItemClickListener {
void OnItemClick(View view, UserBean userBean);
}
public void setmOnItemClickListener(OnRecyclerViewItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
}
public SimpleDataBindingAdapter(Context context) {
super(context);
}
@Override
protected int getLayoutResId(int viewType) {
return R.layout.item_main;
}
@Override
protected void onBindItem(ItemMainBinding binding, UserBean item) {
binding.setUser(item);
binding.getRoot().setOnClickListener(this);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public void onClick(View v) {
if (this.mOnItemClickListener != null) {
mOnItemClickListener.OnItemClick(v, (UserBean) v.getTag());
}
}
}
在MainActivity中只需要和之前一样的调用就可以了。通过数据驱动真的非常的方便。
SimpleDataBindingAdapter simpleDataBindingAdapter = new SimpleDataBindingAdapter(this);
simpleDataBindingAdapter.getItems().add(new UserBean("张三", 18));
simpleDataBindingAdapter.getItems().add(new UserBean("李四", 18));
mRecyclerView.setAdapter(simpleDataBindingAdapter);
simpleDataBindingAdapter.setmOnItemClickListener(new SimpleDataBindingAdapter.OnRecyclerViewItemClickListener() {
@Override
public void OnItemClick(View view, UserBean userBean) {
Toast.makeText(MainActivity.this, userBean.getName(), Toast.LENGTH_LONG).show();
}
});
参考资料: