手写一个RecycleView的BaseQuickAdapter
程序员文章站
2022-05-15 19:26:38
...
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