Android开发中RecyclerView几乎全面取代ListView、GridView,是日常开发中使用频率比较高的控件,谈到RecyclerView那Adapter必不可少,但是在开发中使用Android API提供的Adapter需要写不少重复的代码,所以有必要对其做一定的封装,以减少开发工作量,下面是我针对RecyclerView Adapter封装的一个BaseAdapter和BaseViewHolder。
优点:
- 基本和onCreateViewHolder、getItemCount等方法说拜拜
- 统一设置Item监听和ItemView监听并能按需实现
- 统一封装控件各种常用设置方法,只需直接使用即可,eg设置标题 在bind方法中viewHolder.setText(R.id.tv,"标题")即可
- 统一封装Adapter常用方法,子类直接使用即可
- 其他
代码如下(代码中有相应的注释,有不明白的地方直接查看即可):
BaseAdapter:
/**
* BaseAdapter
* @param
*/
public abstract class BaseAdapter extends RecyclerView.Adapter {
protected List mDataList;
protected Context mContext;
@LayoutRes
protected int mItemLayoutRes;
/**
* 为了在一个Activity/Fragment有多个Adapter时区分不同类型
*/
protected Object mType;
private BaseViewHolder.OnItemClickListener mOnItemClickListener;
private BaseViewHolder.OnItemViewClickListener mOnItemViewClickListener;
protected LayoutInflater mLayoutInflater;
public BaseAdapter(Context context, @LayoutRes int itemLayoutRes, @Nullable Object type) {
mContext = context;
mItemLayoutRes = itemLayoutRes;
mType = type;
mDataList = new ArrayList<>();
mLayoutInflater = LayoutInflater.from(context);
}
/**
* 设置监听
* @param onItemClickListener
*/
public void setOnItemClickListener(BaseViewHolder.OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public void setOnItemViewClickListener(BaseViewHolder.OnItemViewClickListener onItemViewClickListener) {
mOnItemViewClickListener = onItemViewClickListener;
}
/**
* 适合分页加载
*
* @param dataList
* @param isFirst
*/
public void refreshAdapter(@NonNull List dataList, boolean isFirst) {
if (isFirst) {//第一次添加
mDataList.clear();
mDataList.addAll(dataList);
notifyDataSetChanged();
} else {
int preSize = mDataList.size();
mDataList.addAll(dataList);
notifyItemRangeInserted(preSize, Config.LOAD_PAGE_SIZE);
}
}
/**
* 适合初始加载
*
* @param dataList
*/
public void refreshAdapter(@NonNull List dataList) {
if (dataList == null) return;
mDataList.clear();
mDataList.addAll(dataList);
notifyDataSetChanged();
}
public void removeItem(int position) {
mDataList.remove(position);
notifyItemRemoved(position);
}
public void clearAdaper() {
mDataList.clear();
notifyDataSetChanged();
}
public boolean isNonEmpty() {
return !mDataList.isEmpty();
}
public List getDataList() {
return mDataList;
}
public ImageLoader getImageLoader() {
return ImageLoader.getInstance();
}
public void refreshAdapter(int position) {
notifyItemChanged(position);
}
public T getItemDataByPosition(@IntRange(from = 0) int position) {
return mDataList.get(position);
}
public Context getContext() {
return mContext;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View layout = mLayoutInflater.inflate(mItemLayoutRes, viewGroup, false);
return new BaseViewHolder(layout);
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder t, int i) {
T itemData = mDataList.get(i);
setOnItemClickListener(t, itemData, i);
bind(t, itemData, i);
}
protected void setOnItemClickListener(@NonNull final BaseViewHolder viewHolder, final T itemData, final int position) {
/**
* 为了避免单独设置监听,只要Activity设置了监听这里就直接转换设置了
*/
if (mContext instanceof BaseViewHolder.OnItemClickListener) {
mOnItemClickListener = (BaseViewHolder.OnItemClickListener) mContext;
}
if (mOnItemClickListener != null) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnItemClickListener.onItemClick(viewHolder, position, itemData, mType);
}
});
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
mOnItemClickListener.onItemLongClick(viewHolder, position, itemData, mType);
return true;
}
});
}
}
protected void setOnItemViewClickListener(@NonNull final BaseViewHolder viewHolder, View view, final T itemData, final int position) {
if (mContext instanceof BaseViewHolder.OnItemViewClickListener) {
mOnItemViewClickListener = (BaseViewHolder.OnItemViewClickListener) mContext;
}
if (mOnItemViewClickListener != null) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnItemViewClickListener.onItemViewClick(viewHolder, view, position, itemData, mType);
}
});
view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
mOnItemViewClickListener.onItemViewLongClick(viewHolder, view, position, itemData, mType);
return true;
}
});
}
}
@Override
public int getItemCount() {
return mDataList.size();
}
/**
* 子类实现并在里填充数据
*
* @param viewHolder
* @param itemData
* @param position
*/
public abstract void bind(@NonNull BaseViewHolder viewHolder, T itemData, int position);
}
BaseViewHolder:
/**
* BaseViewHolder
*/
public class BaseViewHolder extends RecyclerView.ViewHolder {
private SparseArray mViewSparseArray;
public BaseViewHolder(View itemView) {
super(itemView);
}
public interface OnItemClickListener {
void onItemClick(BaseViewHolder viewHolder, int position, T itemData, Object type);
void onItemLongClick(BaseViewHolder viewHolder, int position, T itemData, Object type);
}
public interface OnItemViewClickListener {
void onItemViewClick(BaseViewHolder viewHolder, View view, int position, T itemData, Object type);
void onItemViewLongClick(BaseViewHolder viewHolder, View view, int position, T itemData, Object type);
}
/**
* 获取Item里的控件
* @param viewId
* @param
* @return
*/
public V getView(@IdRes int viewId) {
if (mViewSparseArray == null) {
mViewSparseArray = new SparseArray<>();
}
View view = mViewSparseArray.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
mViewSparseArray.put(viewId, view);
}
return (V) view;
}
/****************************************各种设置方法******************************************************/
public void setText(@IdRes int viewId, @StringRes int text) {
this.getView(viewId).setText(text);
}
public void setText(@IdRes int viewId, String text) {
this.getView(viewId).setText(text);
}
public void setImageBitmap(@IdRes int viewId, Bitmap bitmap) {
this.getView(viewId).setImageBitmap(bitmap);
}
public void setImageResource(@IdRes int viewId, @DrawableRes int resId) {
this.getView(viewId).setImageResource(resId);
}
public void setBackgroundColor(@IdRes int viewId, @ColorRes int colorRes) {
this.getView(viewId).setBackgroundColor(Utils.getColor(colorRes));
}
public void setBackground(@IdRes int viewId, @DrawableRes int resId) {
this.getView(viewId).setBackground(Utils.getDrawable(resId));
}
public void setBackgroundAlpha(@IdRes int viewId, @IntRange(from = 0, to = 255) int alpha) {
this.getView(viewId).getBackground().mutate().setAlpha(alpha);
}
public void setVisibility(@IdRes int viewId, boolean isShow) {
if (isShow) {
this.getView(viewId).setVisibility(View.VISIBLE);
} else {
this.getView(viewId).setVisibility(View.GONE);
}
}
}
代码没有什么难点,这里再举一个使用栗子
Adapter使用:
public class ExhibitionAdapter extends BaseAdapter {
public ExhibitionAdapter(Context context, int itemLayoutRes, @Nullable Object type) {
super(context, itemLayoutRes, type);
}
@Override
public void bind(@NonNull BaseViewHolder viewHolder, ExhibitionResponseListBody itemData, int position) {
//星级评价
LinearLayout liEvaluate = viewHolder.getView(R.id.li_item_exhibition_spot_evaluate);
liEvaluate.removeAllViews();
int star = itemData.getStar();
if (star > Config.EXHIBITION_STAR || star < 0) {
star = Config.EXHIBITION_STAR;
}
for (int i = 0; i < Config.EXHIBITION_STAR; i++) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams((int) Utils.getDimen(R.dimen.spot_evaluate_width)
, (int) Utils.getDimen(R.dimen.spot_evaluate_height));
layoutParams.rightMargin = (int) Utils.getDimen(R.dimen.spot_evaluate_margin);
ImageView imageView = new ImageView(getContext());
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
//星级
if (i < star) {
imageView.setImageResource(R.mipmap.icon_spot_evaluate_selcted);
} else {
imageView.setImageResource(R.mipmap.icon_spot_evaluate_unseclcted);
}
//补全星级
imageView.setLayoutParams(layoutParams);
liEvaluate.addView(imageView);
}
getImageLoader().load(getContext(),
viewHolder.getView(R.id.img_item_exhibition_spot_img)
, itemData.getCover(), R.mipmap.icon_default_pic, R.mipmap.icon_default_pic, Config.IMAGE_CORNER);
viewHolder.setText(R.id.tv_item_exhibition_spot_age, "年代:" + StringUtil.setText(itemData.getAge()));
viewHolder.setText(R.id.tv_item_exhibition_spot_name, StringUtil.setText(itemData.getName()));
}
}
设置监听:
public class ExhibitionFragment extends BaseMVPFragment
implements ExhibitionContract.View, BaseViewHolder.OnItemClickListener, OnRefreshListener, OnLoadMoreListener {
@Override
public void onItemClick(BaseViewHolder viewHolder, int position, ExhibitionResponseListBody itemData, Object type) {
//TODO
}
@Override
public void onItemLongClick(BaseViewHolder viewHolder, int position, ExhibitionResponseListBody itemData, Object type) {
//TODO
}
}
以上就是针对RecyclerView Adapter的封装,可减少较多重复代码,读者有什么不同观点或疑问请留言指出!!!