欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

手写一个RecycleView的BaseQuickAdapter

程序员文章站 2022-05-15 19:26:38
...

1、概述

手写一个RecycleView的BaseQuickAdapter

如上图,整个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