手写一个RecycleView的BaseQuickAdapter

来源:互联网 发布:手机汽车设计软件 编辑:程序博客网 时间:2024/05/24 15:42

1、概述


如上图,整个BaseQuickAdapter的结构还是很简单的,BaseViewHolder负责缓存item View以及常用的操作的封装,而convert抽象方法是我们在BaseQuickAdapter抽象类中暴露给用户的方法,用户只需实现该方法,并在该方法中绑定数据即可,无需了解BaseViewHolder实现的细节。

2、使用

不使用BaseQuickAdapter的代码:

public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyViewHolder> {    private List<String> data;    //支持点击/长按事件    private OnClick clickLisener;    private OnLongClick longClickLisener;    public MyRecycleViewAdapter(List<String> data) {        this.data = data;    }    public void setClickLisener(OnClick clickLisener) {        this.clickLisener = clickLisener;    }    public void setLongClickLisener(OnLongClick longClickLisener) {        this.longClickLisener = longClickLisener;    }    public interface OnClick {        void myOnClick(View view);    }    public interface OnLongClick {        boolean myOnLongClick(View view);    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        return new MyViewHolder(LayoutInflater.from(MyApplication.context)                .inflate(R.layout.item_recycleview, parent, false));    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        holder.tv_content.setText(data.get(position));        holder.ll.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                clickLisener.myOnClick(v);            }        });        holder.ll.setOnLongClickListener(new View.OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                return longClickLisener.myOnLongClick(v);            }        });    }    @Override    public int getItemCount() {        return data.size();    }    class MyViewHolder extends RecyclerView.ViewHolder {        LinearLayout ll;        TextView tv_content;        public MyViewHolder(View itemView) {            super(itemView);            tv_content = (TextView) itemView.findViewById(R.id.tv_content);            ll = (LinearLayout) itemView.findViewById(R.id.ll);        }    }}

使用BaseQuickAdapter的代码:

public class MyRecycleViewAdapter2 extends BaseQuickAdapter<String> {    public MyRecycleViewAdapter2(List<String> data, int layoutId) {        super(data, layoutId);    }    @Override    public void convert(BaseViewHolder baseViewHolder, String itemData) {        baseViewHolder.setText(R.id.tv_content, itemData);        baseViewHolder.setOnClickLisener(R.id.ll, new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MyApplication.context, "点击事件", Toast.LENGTH_SHORT).show();            }        });        baseViewHolder.setOnLongClickLisener(R.id.ll, new View.OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                Toast.makeText(MyApplication.context, "长按点击事件", Toast.LENGTH_SHORT).show();                return false;            }        });    }}
通过封装BaseQuickAdapter,我们可以发现代码量明显减少了,开发效率必然也就提高了。

3、BaseViewHolder

ViewHolder是RecycleView复用的基本单位,BaseViewHolder将ItemView包含的子View缓存起来以及item常用的操作,包括setText、setImageResource等等封装起来,这样就不用重复书写这些代码,实现整体的复用。

public class BaseViewHolder extends RecyclerView.ViewHolder {    private View convertView;    private SparseArray<View> views;//item view缓存    public BaseViewHolder(View itemView) {        super(itemView);        convertView = itemView;        views = new SparseArray<>();    }    //从SparseArray<View> views中查找,有则返回view,无则先缓存再返回view;    private View getView(int viewId) {        View view = views.get(viewId);        if (view == null) {            view = convertView.findViewById(viewId);            views.put(viewId, view);        }        return view;    }    //TextView setText    public void setText(int viewId, String content) {        ((TextView) getView(viewId)).setText(content);    }    //示例:ImageView 设置背景图    public void setImageResource(int viewId, int drawableId) {        View view = getView(viewId);        if (view instanceof ImageView) {            ((ImageView) view).setImageResource(drawableId);        } else            return;    }    //....其他各种set、get方法.....}
SparseArray<View> views是我们缓存一个item里面子view的集合,这样我们再次使用子view的时候就不需要重复的findViewById了。

3、BaseQuickAdapter

BaseQuickAdapter是一个抽象类,将公用的方法onCreateViewHolder和onBindViewHolder、getItemCount封装起来,这样就不用每次都写这些方法了,有效的减小代码量。同时仅将convert方法暴露出来,只需实现convert方法,并在该方法中绑定数据即可。这里数据的绑定就用到了我们之前封装的BaseViewHolder。

public abstract class BaseQuickAdapter<K> extends RecyclerView.Adapter<BaseViewHolder> {    private List<K> data;    private int layoutId;    //暴露给用户的接口,绑定数据    public abstract void convert(BaseViewHolder baseViewHolder, K itemData);    public BaseQuickAdapter(List<K> data, int layoutId) {        this.data = data;        this.layoutId = layoutId;    }    @Override    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        return new BaseViewHolder(LayoutInflater.from(MyApplication.context).inflate(layoutId, parent, false));    }    @Override    public void onBindViewHolder(BaseViewHolder holder, int position) {        if (data == null || data.size() == 0)            return;        convert(holder, data.get(position));//注意:convert方法必须在onBindViewHolder中调用,将ViewHolder和数据给用户进行绑定    }    @Override    public int getItemCount() {        return data == null ? 0 : data.size();    }}
done!
源码:https://github.com/sparkerandroid/BaseQuickAdapter