RecyclerView
简化Adapter
在实际的开发中,我们的项目中可能存在多个列表,每个列表都必须创建一个Adapter。每一个Adapter都有大量的重复代码,比如onCreateViewHolder方法,每个adapter的操作都差不多,获取view,然后创建一个ViewHolder并返回。我们可以保留相同的操作,将不同的操作抽取出来,达到简化代码的效果。
下面是我进行抽取和封装一个BaseRecyclerViewAdapter:
public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter {
private List<T> mList;
private Context mContext;
private OnItemClickListener mOnItemClickListener;
public static final int TYPE_HEADER = 100;
public static final int TYPE_FOOTER = 101;
private List<View> mHeaders = new ArrayList<>();
private List<View> mFooters = new ArrayList<>();
public interface OnItemClickListener {
void onItemClick(View v, int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public BaseRecyclerViewAdapter(Context context, List<T> list) {
mContext = context;
mList = list;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType != TYPE_HEADER && viewType != TYPE_FOOTER) {
AdapterItem<T> item = createAdapterItem();
View view = LayoutInflater.from(mContext).inflate(item.getLayoutResId(viewType), parent, false);
return new ViewHolder(view, createAdapterItem());
} else {
FrameLayout frameLayout = new FrameLayout(parent.getContext());
frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new HeaderFooterViewHolder(frameLayout);
}
}
public abstract AdapterItem<T> createAdapterItem();
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (isHeader(position)) {
View v = mHeaders.get(position);
prepareHeaderFooter((HeaderFooterViewHolder) holder, v);
} else if (isFooter(position)) {
View v = mFooters.get(position - mList.size() - mHeaders.size());
prepareHeaderFooter((HeaderFooterViewHolder) holder, v);
} else {
T t = mList.get(position - mHeaders.size());
((ViewHolder) holder).item.bindData(mContext, position, t, getItemViewType(position));
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(v -> {
mOnItemClickListener.onItemClick(v, position);
});
}
}
}
private void prepareHeaderFooter(HeaderFooterViewHolder vh, View view) {
if (view.getParent() != null) {
((ViewGroup) view.getParent()).removeView(view);
}
vh.base.removeAllViews();
vh.base.addView(view);
}
@Override
public int getItemCount() {
return mHeaders.size() + mList.size() + mFooters.size();
}
private boolean isHeader(int position) {
return (position < mHeaders.size());
}
private boolean isFooter(int position) {
return (position >= mHeaders.size() + mList.size());
}
@Override
public int getItemViewType(int position) {
if (isHeader(position)) {
return TYPE_HEADER;
} else if (isFooter(position)) {
return TYPE_FOOTER;
} else {
T t = mList.get(position - mHeaders.size());
return createViewType(position, t);
}
}
public abstract int createViewType(int position, T t);
public boolean hasFooter() {
return mFooters.size() > 0;
}
public void addHeader(View header) {
if (!mHeaders.contains(header)) {
mHeaders.add(header);
notifyItemInserted(mHeaders.size() - 1);
}
}
public void removeHeader(View header) {
if (mHeaders.contains(header)) {
notifyItemRemoved(mHeaders.indexOf(header));
mHeaders.remove(header);
}
}
public void addFooter(View footer) {
if (!mFooters.contains(footer)) {
mFooters.add(footer);
notifyItemInserted(mHeaders.size() + mList.size() + mFooters.size() - 1);
}
}
public void removeFooter(View footer) {
if (mFooters.contains(footer)) {
notifyItemRemoved(mHeaders.size() + mList.size() + mFooters.indexOf(footer));
mFooters.remove(footer);
}
}
static class ViewHolder<T> extends RecyclerView.ViewHolder {
protected AdapterItem<T> item;
protected ViewHolder(View itemView, AdapterItem<T> item) {
super(itemView);
this.item = item;
this.item.bindViews(itemView);
}
}
public static class HeaderFooterViewHolder extends RecyclerView.ViewHolder {
FrameLayout base;
public HeaderFooterViewHolder(View itemView) {
super(itemView);
base = (FrameLayout) itemView;
}
}
}我们通过观察可以发现,每个Adapter不同的地方就是布局文件不同和绑定数据不一样。我们封装了一个AdapterItem的类来处理这些不同的操作。
多个不同的列表我们就不需要创建多个Adapter,只需要实现自己的AdapterItem传给BaseRecyclerViewAdapter即可。AdapterItem相比创建一个Adapter代码量少很多。
更多阅读
最后更新于