首先判断当前加载哪种布局,重写getItemViewType方法
if (position == 0) {
if (head_layout_id != 0) {
return TYPE_HEAD;
} else {
return TYPE_NULL;
}
}
if (position + 1 == getItemCount()) {
if (foot_layout_id != 0) {
return TYPE_FOOT;
} else {
return TYPE_NULL;
}
}
return TYPE_NORMAL;
在onCreateViewHolder中根据不同的viewType加载不同的布局,最好确保返回值不为空,不然可能会抛出异常
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEAD:
headView = inflater.inflate(head_layout_id, parent, false);
return createHeadView(parent, viewType);
case TYPE_NORMAL:
itemView = inflater.inflate(normal_layout_id, parent, false);
return createItemView(parent, viewType);
case TYPE_FOOT:
footView = inflater.inflate(foot_layout_id, parent, false);
return createFootView(parent, viewType);
default:
return new BaseViewHolder(new View(context));
}
}
在onBindViewHolder中根据不同viewType绑定不同数据
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
if (position == 0) {
if (head_layout_id != 0) bindHeadView((HEAD) holder, 0);
} else if (position + 1 == getItemCount()) {
if (foot_layout_id != 0) bindFootView((FOOT) holder, position);
} else {
bindItemView((ITEM) holder, position);
}
}
子类中需重写的方法
protected abstract ITEM createItemView(ViewGroup parent, int viewType);
protected abstract HEAD createHeadView(ViewGroup parent, int viewType);
protected abstract FOOT createFOOTView(ViewGroup parent, int viewType);
protected abstract void bindItemView(ITEM holder, int position);
protected abstract void bindHeadView(HEAD holder, int position);
protected abstract void bindFootView(FOOT holder, int position);
最后是完整的代码
BaseAdapter
public abstract class BaseAdapter<HEAD extends BaseViewHolder, ITEM extends BaseViewHolder, FOOT extends BaseViewHolder, DATA> extends RecyclerView.Adapter<BaseViewHolder> {
private final int TYPE_HEAD = 1;
private final int TYPE_NORMAL = 2;
private final int TYPE_FOOT = 3;
private final int TYPE_NULL = 4;
protected Context context;
protected LayoutInflater inflater;
protected int normal_layout_id;
protected int head_layout_id;
protected int foot_layout_id;
protected List<DATA> dataList;
protected View headView;
protected View itemView;
protected View footView;
protected OnLoadMoreListener onLoadMoreListener;
public BaseAdapter(Context context, int head_layout_id, int layout_id, int foot_layout_id, List<DATA> dataList) {
this.context = context;
this.foot_layout_id = foot_layout_id;
this.head_layout_id = head_layout_id;
this.normal_layout_id = layout_id;
this.dataList = dataList;
this.inflater = LayoutInflater.from(context);
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEAD:
headView = inflater.inflate(head_layout_id, parent, false);
return createHeadView(parent, viewType);
case TYPE_NORMAL:
itemView = inflater.inflate(normal_layout_id, parent, false);
return createItemView(parent, viewType);
case TYPE_FOOT:
footView = inflater.inflate(foot_layout_id, parent, false);
return createFootView(parent, viewType);
default:
return new BaseViewHolder(new View(context));
}
}
protected abstract ITEM createItemView(ViewGroup parent, int viewType);
protected abstract HEAD createHeadView(ViewGroup parent, int viewType);
protected abstract FOOT createFootView(ViewGroup parent, int viewType);
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
if (position == 0) {
if (head_layout_id != 0) bindHeadView((HEAD) holder, 0);
} else if (position + 1 == getItemCount()) {
if (foot_layout_id != 0) bindFootView((FOOT) holder, position);
} else {
bindItemView((ITEM) holder, dataList.get(position - 1));
}
}
protected abstract void bindItemView(ITEM holder, DATA data);
protected abstract void bindHeadView(HEAD holder, int position);
protected abstract void bindFootView(FOOT holder, int position);
@Override
public int getItemViewType(int position) {
if (position == 0) {
if (head_layout_id != 0) {
return TYPE_HEAD;
} else {
return TYPE_NULL;
}
}
if (position + 1 == getItemCount()) {
if (foot_layout_id != 0) {
return TYPE_FOOT;
} else {
return TYPE_NULL;
}
}
return TYPE_NORMAL;
}
@Override
public int getItemCount() {
return dataList.size() + 2;
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public void clearData() {
if (dataList != null) dataList.clear();
}
public void addData(List<DATA> moreList) {
dataList.addAll(moreList);
}
//可手动添加一个加载更多失败的回调
public interface OnLoadMoreListener {
void loadMore(BaseViewHolder footHolder);
}
}
BaseViewHolder
public class BaseViewHolder extends RecyclerView.ViewHolder {
public BaseViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
DATA为需要绑定的数据类型
使用
依次传入头部,正常item,底部布局的ViewHolder还有实现数据绑定的数据类型
public class DemoAdapter extends BaseAdapter<HeadViewHolder,AdviceViewHolder,FootViewHolder,DesignAdvice>{
public DemoAdapter(Context context, int foot_layout_id, int head_layout_id, int layout_id, List<DesignAdvice> designAdvices) {
super(context, foot_layout_id, head_layout_id, layout_id, designAdvices);
}
@Override
protected AdviceViewHolder createItemView(ViewGroup parent, int viewType) {
return new AdviceViewHolder(itemView);
}
@Override
protected HeadViewHolder createHeadView(ViewGroup parent, int viewType) {
return new HeadViewHolder(headView);
}
@Override
protected FootViewHolder createFootView(ViewGroup parent, int viewType) {
return new FootViewHolder(footView);
}
@Override
protected void bindItemView(AdviceViewHolder holder, DesignAdvice designAdvice) {
//操作数据
holder.title.setText(designAdvice.getTitle());
holder.itemView.setTag(designAdvice);
}
@Override
protected void bindHeadView(HeadViewHolder holder, int position) {
}
@Override
protected void bindFootView(FootViewHolder holder, int position) {
}
}
有时候我们并不需要头部和底部的布局,但直接继承这个BaseAdapter还是会有些多余的代码,所以我决定进一步封装一个只有正常item的adapter
DataAdapter
public abstract class DataAdapter<ITEM extends BaseViewHolder, DATA> extends BaseAdapter<BaseViewHolder, ITEM, BaseViewHolder, DATA> {
public DataAdapter(Context context, int layout_id, List<DATA> datas) {
super(context, 0, layout_id, 0, datas);
}
@Override
protected BaseViewHolder createHeadView(ViewGroup parent, int viewType) {
return null;
}
@Override
protected BaseViewHolder createFootView(ViewGroup parent, int viewType) {
return null;
}
@Override
protected void bindHeadView(BaseViewHolder holder, int position) {
}
@Override
protected void bindFootView(BaseViewHolder holder, int position) {
}
}
代码也很简单,继承BaseAdapter,顶部和底部的布局id传入0即可,然后重写他们的createView和bindView方法。
使用
public class DemoAdapter extends DataAdapter<AdviceViewHolder, DesignAdvice> {
public DemoAdapter(Context context, int layout_id, List<DesignAdvice> designAdvices) {
super(context, layout_id, designAdvices);
}
@Override
protected AdviceViewHolder createItemView(ViewGroup parent, int viewType) {
return new AdviceViewHolder(itemView);
}
@Override
protected void bindItemView(AdviceViewHolder holder, DesignAdvice designAdvice) {
holder.title.setText(designAdvice.getTitle());
holder.itemView.setTag(designAdvice);
}
}
直接传入布局的ViewHolder和需要处理的数据。我们只要把精力放在bindView中数据的显示即可了。需要写的代码基本只在bindView中了。也不用再去频繁的根据position获取List中的数据了,这些工作都已经封装好了。
类似的还可以封装有head和item的adapter以及有foot和item的adapter。要是三种都需要就使用BaseAdapter。
有底部布局和item的Adapter
public abstract class DataWFootAdapter<ITEM extends BaseViewHolder, FOOT extends BaseViewHolder, DATA> extends BaseAdapter<BaseViewHolder, ITEM, FOOT, DATA> {
public DataWFootAdapter(Context context, int layout_id, int foot_layout_id, List<DATA> datas) {
super(context,0, layout_id, foot_layout_id, datas);
}
@Override
protected BaseViewHolder createHeadView(ViewGroup parent, int viewType) {
return null;
}
@Override
protected void bindHeadView(BaseViewHolder holder, int position) {
}
}
有头部布局的Adapter
public abstract class DataWHeadAdapter<HEAD extends BaseViewHolder,ITEM extends BaseViewHolder, DATA> extends BaseAdapter<HEAD, ITEM, BaseViewHolder, DATA>{
public DataWHeadAdapter(Context context, int head_layout_id, int layout_id, int foot_layout_id, List<DATA> datas) {
super(context, head_layout_id, layout_id, foot_layout_id, datas);
}
@Override
protected BaseViewHolder createFootView(ViewGroup parent, int viewType) {
return null;
}
@Override
protected void bindFootView(BaseViewHolder holder, int position) {
}
}