MVVM模式下RecyclerView与databinding的结合

如果不知道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 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取代了,小伙伴们可以根据自己的需求进行具体操作

MVVM模式下RecyclerView与databinding的结合(2)

参考资料:http://www.cnblogs.com/DoNetCoder/p/7243878.html?utm_source=tuicool&utm_medium=referral

发布了30 篇原创文章 · 获赞 20 · 访问量 7万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览