您的位置:首页 > 其它

MVVM模式下RecyclerView与databinding的结合

2018-01-11 18:16 218 查看
如果不知道databinding的小伙伴,建议去了解下,非常实用,尤其是与RecyclerView等控件结合的时候,方便快捷,爱不释手。

首先看一下,传统RecyclerView和Adapter如何设置及处理数据的

RecyclerView recyclerView = dataBindingBinding.recyclerView;
recyclerView.setLayoutManager(new LinearLayoutManager(this));

mList.add(new User("张三", "21"));
mList.add(new User("李四", "22"));
mList.add(new User("王五", "23"));
mList.add(new User("赵六", "24"));
MySimpleAdapter adapter = new MySimpleAdapter(this,mList);
recyclerView.setAdapter(adapter);


public class MySimpleAdapter extends RecyclerView.Adapter{

private Context mContext;
private List<User> mList;

public MySimpleAdapter(Context context, List<User> list){
mContext = context;
mList = list;
}

public static class SimpleViewHolder extends RecyclerView.ViewHolder {
TextView name,age;
SimpleViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.textView);
age = (TextView) view.findViewById(R.id.textView7);
}

}

@Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_data_binding, parent, false);
return new SimpleViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final SimpleViewHolder mSimpleViewHolder = ((SimpleViewHolder) holder);

mSimpleViewHolder.name.setText(mList.get(position).getName());
mSimpleViewHolder.age.setText(mList.get(position).getAge());
}

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


User类就是一个name和age属性,R.layout.adapter_data_binding 就两个TextView展示name和age,很简单,就不展示了。

一般传统的adapter写法,就是在传入一个context和一个list,然后在自己建的ViewHolder中通过findViewById找到相关的TextView、ImageView等控件,再在onBindViewHolder中设置各种信息。如果控件多了的话,findViewById就很痛苦,虽然有ButterKnife可以减少工作量,但是还是比较麻烦。

但是如果RecyclerView是用dataBinding来处理的话,事半功倍,下面附上使用后的代码:

RecyclerView recyclerView = dataBindingBinding.recyclerView;
recyclerView.setLayoutManager(new LinearLayoutManager(this));

SimpleDataBindingAdapter simpleDataBindingAdapter = new SimpleDataBindingAdapter(this);
simpleDataBindingAdapter.getItems().add(new User("张三", "21"));
simpleDataBindingAdapter.getItems().add(new User("李四", "22"));
simpleDataBindingAdapter.getItems().add(new User("王五", "23"));
simpleDataBindingAdapter.getItems().add(new User("赵六", "24"));

recyclerView.setAdapter(simpleDataBindingAdapter);


public class SimpleDataBindingAdapter extends BaseBindingAdapter<User,AdapterDataBindingBinding> {

public SimpleDataBindingAdapter(Context context) {
super(context);
}

@Override
protected int getLayoutResId(int viewType) {
return R.layout.adapter_data_binding;
}

@Override
protected void onBindItem(AdapterDataBindingBinding binding, User item) {
binding.setUser(item);
}
}


是不是觉得特别简洁?瞬间感觉清爽很多。使用的方式很简单,建立一个自己的adapter,继承BaseBindingAdapter,并传入两个参数,一个是list要处理的对象类User,另一个则是dataBinding所对应的R.layout.xxxx文件。通过onBindItem方法,就可以返回对应的布局和对象数据。

下面我们看看BaseBindingAdapter这个类的“庐山真面目”

public abstract class BaseBindingAdapter<M, B extends
4000
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) {
B binding = DataBindingUtil.getBinding(holder.itemView);
this.onBindItem(binding, this.items.get(position));
}

@LayoutRes
protected abstract int getLayoutResId(int viewType);

protected abstract void onBindItem(B binding, M item);

}


其中RecyclerView最核心的两个方法onCreateViewHolder,onBindViewHolder

@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) {
B binding = DataBindingUtil.getBinding(holder.itemView);
this.onBindItem(binding, this.items.get(position));
}


这个B就是传进来的R.layout.xxxx对应的dataBinding类,getLayoutResId方法返回值就是设置的R.layout.xxxx,之后触发onBindItem进行回调,返回对应的adapter布局和对象类。

这样,一个最简单的RecyclerView与databinding的结合的adapter就完成了,小伙伴们,可以直接复制BaseBindingAdapter这个类去使用。

补充说明:

在实际操作中,我们还会经常对adapter的List数据进行增删改操作,然后使用notifyDataSetChanged()方法进行更新,为了更方便的进行数据实时更新,BaseBindingAdapter中使用了ObservableArrayList这个类,这个类可以进行数据的更新监听,具体操作我附上代码

public abstract class BaseBindingAdapter<M, B extends ViewDataBinding> extends RecyclerView.Adapter {
protected Context context;
protected ObservableArrayList<M> items;
protected ListChangedCallback itemsChangeCallback;

public BaseBindingAdapter(Context context) {
this.context = context;
this.items = new ObservableArrayList<>();
this.itemsChangeCallback = new ListChangedCallback();
}

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) { B binding = DataBindingUtil.getBinding(holder.itemView); this.onBindItem(binding, this.items.get(position)); }

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.items.addOnListChangedCallback(itemsChangeCallback);
}

@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
this.items.removeOnListChangedCallback(itemsChangeCallback);
}

//region 处理数据集变化
protected void onChanged(ObservableArrayList<M> newItems) {
resetItems(newItems);
notifyDataSetChanged();
}

protected void onItemRangeChanged(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeChanged(positionStart, itemCount);
}

protected void onItemRangeInserted(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeInserted(positionStart, itemCount);
}

protected void onItemRangeMoved(ObservableArrayList<M> newItems) {
resetItems(newItems);
notifyDataSetChanged();
}

protected void onItemRangeRemoved(ObservableArrayList<M> newItems, int positionStart, int itemCount) {
resetItems(newItems);
notifyItemRangeRemoved(positionStart, itemCount);
}

protected void resetItems(ObservableArrayList<M> newItems) {
this.items = newItems;
}

@LayoutRes
protected abstract int getLayoutResId(int viewType);

protected abstract void onBindItem(B binding, M item);

private class ListChangedCallback extends ObservableArrayList.OnListChangedCallback<ObservableArrayList<M>> {
@Override
public void onChanged(ObservableArrayList<M> newItems) {
BaseBindingAdapter.this.onChanged(newItems);
}

@Override
public void onItemRangeChanged(ObservableArrayList<M> newItems, int i, int i1) {
BaseBindingAdapter.this.onItemRangeChanged(newItems, i, i1);
}

@Override
public void onItemRangeInserted(ObservableArrayList<M> newItems, int i, int i1) {
BaseBindingAdapter.this.onItemRangeInserted(newItems, i, i1);
}

@Override
public void onItemRangeMoved(ObservableArrayList<M> newItems, int i, int i1, int i2) {
BaseBindingAdapter.this.onItemRangeMoved(newItems);
}

@Override
public void onItemRangeRemoved(ObservableArrayList<M> sender, int positionStart, int itemCount) {
BaseBindingAdapter.this.onItemRangeRemoved(sender, positionStart, itemCount);
}
}
}


以上这段代码是我复制网上一位大神的源码,在实际的操作中,我发现notifyDataSetChanged()比notifyItemRangeChanged、notifyItemRangeInserted等方法更加实用,为此我更改了一下源码,将里面的更新item的操作都用notifyDataSetChanged取代了,小伙伴们可以根据自己的需求进行具体操作

参考资料:http://www.cnblogs.com/DoNetCoder/p/7243878.html?utm_source=tuicool&utm_medium=referral
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息