RcyclerView DataBinding结合

最近在将自己之前的项目从MVP更改到MVVM,遇到了一些坑,也学习了不少。记录下自己怎么去解决RcyclerView和DataBinding结合的过程。本文的前提是假设你有一部分的MVVM的基础,并且知道如何是用DataBinding。

重点

先说重点,RcyclerView和DataBinding结合最重要的其实就两个方法:

  • onCreateViewHolder()中ViewHolder获取了对View的引用,方便快速的处理数据
  • onBindViewHolder()中将指定的数据传送给View

实现

为了达到通用的目的,我创建了一个基础的Adapter。按照上面说的两个重要方法。我们看看如何实现:

onCreateViewHolder()

1
2
3
4
5
@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()

1
2
3
4
5
6
@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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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

有了上面的基类,实现起来就挺方便了。直接看代码就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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中只需要和之前一样的调用就可以了。通过数据驱动真的非常的方便。

1
2
3
4
5
6
7
8
9
10
11
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();
}
});

参考资料:

请我喝一杯啤酒~