目前在越来越多的项目中都会使用到RecyclerView,在这样高频使用的场景,我们应该尝试着进行二次封装,将会减少我们很大的代码量。
演示:
- new 匿名内部内的方式:
rl_list.setAdapter(new BaseAdapter<String>(mContext, list, R.layout.item_rl_list) {
@Override
public void onBind(ViewHolder holder, int position, String item) {
holder.view(R.id.iv_img).setBackgroundResource(R.mipmap.ic_launcher).view(R.id.tv_name).setText(item);
}
});
- 对象继承的方式:
TestAdapter testAdapter=new TestAdapter(mContext, list, R.layout.item_rl_list);
rl_list.setAdapter(testAdapter);
public class TestAdapter extends BaseAdapter<String> {
public TestAdapter(Context context, List<String> mDatas, int layoutId) {
super(context, mDatas, layoutId);
}
@Override
public void onBind(ViewHolder holder, int position, String item) {
holder.view(R.id.iv_img).setBackgroundResource(R.mipmap.ic_launcher).setText(R.id.tv_name, item);
}
}
特点:
- 支持holder链式调用。
- 只需实现onBind方法,对数据和视图进行绑定。
- 多布局支持,可以在构造方法中实现RLItemViewType接口,或者构造Type传null,然后在Adapter内部实现RLItemViewType接口,多种选择。
- 为了满足实际网络请求案例,支持在构造函数Data传null,然后网络数据返回时,调用BaseAdapter.setData()方法刷新数据,在刷新控件的支持下,加载更多时调用BaseAdapter.addAll()。
适配器实现代码:
public abstract class BaseAdapter<T> extends RecyclerView.Adapter<ViewHolder> implements AdapterInterFace<T> {
private List<T> mData;
private int layoutId;
protected Context mContext;
private RLItemViewType<T> itemViewType;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
/**
* 单布局构造
*/
public BaseAdapter(Context context, List<T> mDatas, int layoutId) {
this.mContext = context;
this.mData = mDatas;
if (this.mData == null) {
this.mData = new ArrayList<>();
}
this.layoutId = layoutId;
this.itemViewType = null;
}
/**
* 多布局构造
*/
public BaseAdapter(Context context, List<T> mDatas, RLItemViewType<T> viewType) {
this.mContext = context;
this.mData = mDatas;
if (this.mData == null) {
this.mData = new ArrayList<>();
}
this.itemViewType = viewType == null ? createViewType() : viewType;
if (itemViewType == null) {
//使用这个构造函数,你必须实现RLItemViewType接口。
new NullPointerException("NullPointerException With this constructor, you must implement the RLItemViewType interface.");
}
}
/**
* 如果多布局未在构造中指定Type时,需要在内部实现此方法
*/
protected RLItemViewType<T> createViewType() {
return null;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
//加载指定item布局
View inflate = LayoutInflater.from(mContext).inflate(itemViewType == null ?
layoutId : itemViewType.getLayoutId(viewType), parent, false);
final ViewHolder holder = new ViewHolder(inflate);
//用户需要监听时,才设置监听事件
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, viewType, holder.getAdapterPosition());
}
});
}
if (mOnItemLongClickListener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mOnItemLongClickListener.onItemLongClick(v, viewType, holder.getAdapterPosition());
return true;
}
});
}
return holder;
}
@Override
public final void onBindViewHolder(ViewHolder holder, int position) {
onBind(holder, position, mData.get(position));
}
@Override
public int getItemCount() {
return mData == null || mData.size() <= 0 ? 0 : mData.size();
}
public void setmOnItemClickListener(OnItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
}
public void setmOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
this.mOnItemLongClickListener = mOnItemLongClickListener;
}
@Override
public void addAll(List<T> data) {
mData.addAll(data);
notifyDataSetChanged();
}
@Override
public void setData(List<T> data) {
mData = data;
notifyDataSetChanged();
}
@Override
public List<T> getData() {
return mData;
}
/**
* 绑定数据操作
*/
public abstract void onBind(ViewHolder holder, int position, T item);
}
多布局接口定义:
public interface RLItemViewType<T> {
int getItemViewType(int position, T t);
@LayoutRes
int getLayoutId(int viewType);
}
适配器接口定义:
public interface AdapterInterFace<T> {
void addAll(List<T> data);
void setData(List<T> data);
List<T> getData();
}
适配器监听接口定义:
public interface OnItemClickListener {
void onItemClick(View itemView, int viewType, int position);
}
public interface OnItemLongClickListener {
void onItemLongClick(View itemView, int viewType, int position);
}
ViewHolder实现代码:
public class ViewHolder extends RecyclerView.ViewHolder {
/**
* 在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加。
*/
private SparseArray<View> childViews = new SparseArray<>();
private View view;
public ViewHolder(View itemView) {
super(itemView);
}
@Deprecated
public <T extends View> T getView(int id) {
return findViewById(id);
}
@SuppressWarnings("unchecked")
public <T extends View> T findViewById(int id) {
View childView = childViews.get(id);
if (childView == null) {
childView = itemView.findViewById(id);
if (childView != null) {
childViews.put(id, childView);
}
}
view = childView;
return (T) childView;
}
// public ExtendViewHolder view(int viewId) {
// return ExtendViewHolder.getInstance(this, findViewById(viewId));
// }
public ViewHolder view(int viewId) {
findViewById(viewId);
return this;
}
public ViewHolder setTag(Object tag) {
view.setTag(tag);
return this;
}
public ViewHolder setOnClickListener(View.OnClickListener listener) {
view.setOnClickListener(listener);
return this;
}
public ViewHolder setBackground(Drawable background) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(background);
}
return this;
}
public ViewHolder setBackgroundColor(@ColorInt int color) {
view.setBackgroundColor(color);
return this;
}
public ViewHolder setBackgroundResource(@DrawableRes int resid) {
view.setBackgroundResource(resid);
return this;
}
public ViewHolder setScaleType(ImageView.ScaleType scaleType) {
if (view instanceof ImageView) {
((ImageView) view).setScaleType(scaleType);
}
return this;
}
public ViewHolder setText(CharSequence text) {
if (view instanceof TextView) {//Button、EditText等控件继承自TextView
((TextView) view).setText(text);
}
return this;
}
public ViewHolder setText(int viewId, CharSequence text) {
View findView = findViewById(viewId);
if (findView instanceof TextView) {//Button、EditText等控件继承自TextView
((TextView) findView).setText(text);
}
return this;
}
public ViewHolder setTextColor(@ColorInt int color) {
if (view instanceof TextView) {
((TextView) view).setTextColor(color);
}
return this;
}
public ViewHolder setTextSize(float size) {
if (view instanceof TextView) {
((TextView) view).setTextSize(size);
}
return this;
}
}