对于adapter我们在熟悉不过了。往往适配器多了也写着烦,都是堆叠代码。。。
为了减少代码量,写一个合理的基类还是挺不错的。
正好,整合最近网上看到的一些资料,以及现在项目中使用的,也来一发。。。
首先还是先来看一下对比的最终效果:
1、正常的RecyclerViewAdapter的写法
public class BaseAdapter2 extends RecyclerView.Adapter<BaseAdapter2.ViewHolder> {
private Context context;
private Fragment fragment;
private LayoutInflater mLayoutInflater;
private List<String> mList;
public BaseAdapter2(Fragment fragment, List<String> mList) {
this.fragment = fragment;
this.mList = mList;
this.context = fragment.getActivity();
mLayoutInflater = LayoutInflater.from(context);
}
/**
* ItemClick的回调接口 ( 如果还有长按监听还得另加 )
*/
public interface OnItemClickListener{
void OnItemClick(View view, int position);
}
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener mOnItemClickListener){
this.mOnItemClickListener=mOnItemClickListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.item_goods_order, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
/**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if(mOnItemClickListener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.OnItemClick(holder.itemView,position);
}
});
}
//此处省略一堆绑定数据
}
@Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
@Optional
TextView tv;
//此处省略一堆
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
}
}
2、简化后的写法
public class ListRcvAdapter extends BaseRcvAdapter<BaseViewHolder> { public ListRcvAdapter(Context context, List<Object> mList) { super(context, mList); } public ListRcvAdapter(Fragment fragment, List<Object> mList) { super(fragment, mList); } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = mLayoutInflater.inflate(R.layout.item_list, parent, false); return new BaseViewHolder(context, view); } @Override public void onBindViewHolder(BaseViewHolder holder, final int position) { super.onBindViewHolder(holder, position); //绑定数据 holder.setText(R.id.tv, mList.get(position).toString()) .setText(R.id.delete, ""); //编辑模式 holder.views.get(R.id.delete).setVisibility(isEdit ? View.VISIBLE : View.GONE); //点击事件 holder.views.get(R.id.delete).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { remove(position); } }); } }
如果适配器一多,每次都需要些这么多重复代码的话。
从几个方面开始优化的:新建一个BaseRcvAdapter继承RecyclerView.Adapter
1、接口,可以把item的点击事件和长按事件放在基类里。 重写他的onBindViewHolder方法
protected OnItemClickListener onItemClickListener; //单击 protected View.OnLongClickListener onLongClickListener; //长按
public interface OnItemClickListener { void onItemClick(View view, int position); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } public void setOnItemLongClickListener(View.OnLongClickListener onLongClickListener) { this.onLongClickListener = onLongClickListener; }
@Override public void onBindViewHolder(VH holder, final int position) { if (onItemClickListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(v, position); } }); } if (onLongClickListener != null) { holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { onLongClickListener.onLongClick(v); return true; } }); } }2、一些全局变量(Fragment、Context、list<Object>数据、LayoutInflater)放在基类里,并重写他的getItemCount()方法
3、可能考虑到长按的时候是整个RecyclerView的所有条目进入编辑模式。也可以考虑写入基类
protected boolean isEdit = false; //是否进入编辑模式
public void setEdit(boolean isEdit) { this.isEdit = isEdit; notifyDataSetChanged(); }
4、对于数据的删除和添加public boolean getEdit() { return isEdit; }
public void remove(int position) { mList.remove(position); notifyItemRemoved(position); } public void add(Integer position, Object item) { mList.add(position, item); notifyItemInserted(position); } public void add(Object item) { mList.add(item); notifyDataSetChanged(); }5、来看看ViewHolder的写法
public class BaseViewHolder extends RecyclerView.ViewHolder { protected SparseArray<View> views; protected Context context; protected Resources resources; protected View convertView; public BaseViewHolder(Context context, View itemView) { super(itemView); this.context = context; this.convertView = itemView; resources = context.getResources(); this.views = new SparseArray<View>(); } /** * 设置TextView内容 * * @param viewId * @param value * @return */ public BaseViewHolder setText(int viewId, CharSequence value) { TextView view = getView(viewId); if (!TextUtils.isEmpty(value)) { view.setText(value); } return this; } public BaseViewHolder setText(int viewId, int value) { TextView view = getView(viewId); view.setText(resources.getString(value)); return this; } /** * 设置SimpleDraweeView的图片 * * @param viewId * @param url * @return */ public BaseViewHolder setSimpleDraweeView(int viewId, String url) { SimpleDraweeView view = getView(viewId); if (!TextUtils.isEmpty(url)) { view.setImageURI(Uri.parse(url)); } return this; } /** * 设置开/关两种状态的按钮 * * @param viewId * @param checked * @return */ public BaseViewHolder setCheck(int viewId, boolean checked) { View view = getView(viewId); if (view instanceof CompoundButton) { ((CompoundButton) view).setChecked(checked); } else if (view instanceof CheckedTextView) { ((CheckedTextView) view).setChecked(checked); } return this; } /** * 设置adapter(ListView/GridView都继承AdapterView) * * @param viewId * @param adapter * @return */ public BaseViewHolder setAdapter(int viewId, Adapter adapter) { AdapterView view = getView(viewId); view.setAdapter(adapter); return this; } /** * 设置Rcv的adapter * * @param viewId * @param adapter * @return */ public BaseViewHolder setRcvAdapter(int viewId, RecyclerView.Adapter adapter) { RecyclerView view = getView(viewId); view.setAdapter(adapter); return this; } /** * 得到相信的view * * @param viewId view的id * @param <T> view本身 * @return */ public <T extends View> T getView(int viewId) { View view = views.get(viewId); if (view == null) { view = convertView.findViewById(viewId); views.put(viewId, view); } return (T) view; } //使用 SparseArray 做缓存 //此处还能继续添加自己想要的控件的初始化赋值等,自行添加。注意:图片我用的是Fresco,可以自己修改 }
具体代码,可查看:https://github.com/zxp19920626/ZxpDemo 里面的BaseRcvAdapter和BaseViewHolder。。。用法可查看ListRcvAdapter