前言
在上一个项目里有很多很多很多很多的RecyclerView,然后我需要写很多很多很多很多的Adapter和Viewholder——多倒没问题,但是里面有很多重复的代码这就不能忍了!每一个Adapter和ViewHolder其实做的事情非常的像:视图绑定,数据绑定,点击事件分发。还有啥?既然它们做的事情都一样,为啥我们还要傻傻的继续写着重复的代码?
正文
BaseAdapter
通常我们要创建一个RecyclerView.Adapter是怎么做的?
- 接收一个数据列表
- 重写getItemCount()方法,确定Item的个数
- 重写onCreateViewHolder()方法,绑定Layout,新建一个我们自己写的RecyclerView.ViewHolder
- 重写onBindViewHolder()方法,进行数据和视图绑定
- 由于RecyclerView没有写点击事件,把点击事件分发出去
基本上就是这个套路,或者再加一个refreshData()的方法——传新的数据进来然后notifyDataSetChanged()。基于这些点,我写了一个BaseAdapter基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/** * Adapter基类. * 适用于只有单个Item的RecyclerView. * * Created by lypeer on 16-5-24. */ public abstract class BaseAdapter<V> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { /** * 装载了每个Item的Value的列表 */ private List<V> mValueList; /** * 我写的一个接口,通过回调分发点击事件 */ private OnItemClickListener<V> mOnItemClickListener; @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return createViewHolder(parent.getContext(), parent); } @Override @SuppressWarnings("unchecked")//一定会是BaseViewHolder的子类,因为createViewHolder()的返回值 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //BaseViewHolder是我抽象出来的RecyclerView.ViewHolder的基类,下面会有详细讲解 ((BaseViewHolder) holder).setData(mValueList.get(position), position, mOnItemClickListener); } /** * 设置每个Item的点击事件 * @param listener */ public void setOnClickListener(OnItemClickListener<V> listener) { this.mOnItemClickListener = listener; } /** * 刷新数据 * @param valueList 新的数据列表 */ public void refreshData(List<V> valueList) { this.mValueList = valueList; notifyDataSetChanged(); } @Override public int getItemCount() { return mValueList == null ? 0 : mValueList.size(); } /** * 生成ViewHolder * @param context * @param parent * @return */ protected abstract BaseViewHolder createViewHolder(Context context, ViewGroup parent); } |
它的子类在继承它的时候需要指定泛型的具体类型,因为不同的Item也许其数据类型并不一样,这样就可以适应更多的Item。另外,其中提到了一个接口OnItemClickListener,这个接口很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * 点击事件的接口 * Created by lypeer on 16-5-24. */ public interface OnItemClickListener<V> { /** * 当item被点击的时候进行事件分发 * * @param itemValue 点击的item传递的值 * @param viewID 点击控件的id * @param position 被点击的item的位置 */ void onItemClick(V itemValue, int viewID, int position); } |
在使用它的时候同样需要使用泛型——原因和上面一样。
通过上面的BaseAdapter,我们把很多的共有操作都封装在了基类里面,而它的子类只需要根据需要新建不同的ViewHolder就行了——当然,这个viewHolder必须继承自BaseViewHolder,而BaseViewHolder是什么下面会有详细讲解。接下来是一个例子,假设我们现在在一个界面要有一个RecyclerView,它的每个Item的数据是一个String值,那么怎么使用我们的BaseAdapter简化开发过程呢?
欢迎加入伯乐在线 专栏作者。
前言
在上一个项目里有很多很多很多很多的RecyclerView,然后我需要写很多很多很多很多的Adapter和Viewholder——多倒没问题,但是里面有很多重复的代码这就不能忍了!每一个Adapter和ViewHolder其实做的事情非常的像:视图绑定,数据绑定,点击事件分发。还有啥?既然它们做的事情都一样,为啥我们还要傻傻的继续写着重复的代码?
正文
BaseAdapter
通常我们要创建一个RecyclerView.Adapter是怎么做的?
- 接收一个数据列表
- 重写getItemCount()方法,确定Item的个数
- 重写onCreateViewHolder()方法,绑定Layout,新建一个我们自己写的RecyclerView.ViewHolder
- 重写onBindViewHolder()方法,进行数据和视图绑定
- 由于RecyclerView没有写点击事件,把点击事件分发出去
基本上就是这个套路,或者再加一个refreshData()的方法——传新的数据进来然后notifyDataSetChanged()。基于这些点,我写了一个BaseAdapter基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/** * Adapter基类. * 适用于只有单个Item的RecyclerView. * * Created by lypeer on 16-5-24. */ public abstract class BaseAdapter<V> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { /** * 装载了每个Item的Value的列表 */ private List<V> mValueList; /** * 我写的一个接口,通过回调分发点击事件 */ private OnItemClickListener<V> mOnItemClickListener; @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return createViewHolder(parent.getContext(), parent); } @Override @SuppressWarnings("unchecked")//一定会是BaseViewHolder的子类,因为createViewHolder()的返回值 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //BaseViewHolder是我抽象出来的RecyclerView.ViewHolder的基类,下面会有详细讲解 ((BaseViewHolder) holder).setData(mValueList.get(position), position, mOnItemClickListener); } /** * 设置每个Item的点击事件 * @param listener */ public void setOnClickListener(OnItemClickListener<V> listener) { this.mOnItemClickListener = listener; } /** * 刷新数据 * @param valueList 新的数据列表 */ public void refreshData(List<V> valueList) { this.mValueList = valueList; notifyDataSetChanged(); } @Override public int getItemCount() { return mValueList == null ? 0 : mValueList.size(); } /** * 生成ViewHolder * @param context * @param parent * @return */ protected abstract BaseViewHolder createViewHolder(Context context, ViewGroup parent); } |
它的子类在继承它的时候需要指定泛型的具体类型,因为不同的Item也许其数据类型并不一样,这样就可以适应更多的Item。另外,其中提到了一个接口OnItemClickListener,这个接口很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * 点击事件的接口 * Created by lypeer on 16-5-24. */ public interface OnItemClickListener<V> { /** * 当item被点击的时候进行事件分发 * * @param itemValue 点击的item传递的值 * @param viewID 点击控件的id * @param position 被点击的item的位置 */ void onItemClick(V itemValue, int viewID, int position); } |
在使用它的时候同样需要使用泛型——原因和上面一样。
通过上面的BaseAdapter,我们把很多的共有操作都封装在了基类里面,而它的子类只需要根据需要新建不同的ViewHolder就行了——当然,这个viewHolder必须继承自BaseViewHolder,而BaseViewHolder是什么下面会有详细讲解。接下来是一个例子,假设我们现在在一个界面要有一个RecyclerView,它的每个Item的数据是一个String值,那么怎么使用我们的BaseAdapter简化开发过程呢?
1 2 3 |