
RecyclerView(二)之Adapter封装
在写RecyclerView的adpter和viewholder之后会发现代码还是很多的,而且每写一个RecyclerView就要重复一遍,其中有很多重复方法可以封装,把RecyclerView的adapter和viewholder封装成通用的是有必要的。
在开始封装前,需要整个封装内容想好,要封装成什么样子,从结果一步一步抽丝剥茧比一开始瞎想一边写一边改要更好,我要封装成的adapter如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class TestRecycleAdapter<T> extends BaseRecyclerAdapter { /** * * @param context * @param layoutId item布局ID * @param data 展示数据 */ public TestRecycleAdapter(Context context, int layoutId, List<T> data) { super(context, layoutId, data); } /** * 绑定数据到每一个item * @param holder * @param position */ @Override public void convert(BaseViewHolder holder, int position) { } }
|
BaseRecyclerAdapter中构造方法传入所需的布局ID和数据列表,在convert方法中展示,该方法即对应onBindViewHolder方法,要实现需要对ViewHolder和adapter分别封装。
BaseViewHolder
ViewHolder的主要的作用,实际上是通过成员变量存储对应的convertView中需要操作的字View,避免每次findViewById,从而提升运行的效率。对于不确定的view ID 想要抽取成通用的部分找到对应的组件只能用集合存储了,如下所示:
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
|
public class BaseViewHolder extends RecyclerView.ViewHolder { protected View mView; protected SparseArray<View> mSparseArray; public BaseViewHolder(View itmeView) { super(itmeView); this.mView = itmeView; mSparseArray = new SparseArray<>(); } public static BaseViewHolder createViewHolder(Context context, int layoutId, ViewGroup parent) { View view = LayoutInflater.from(context).inflate(layoutId, parent); BaseViewHolder baseViewHolder = new BaseViewHolder(view); return baseViewHolder; } /** * 实例化item中的视图控件,并缓存到SparseArray中 * 在绑定数据和设置子view监听时,通过ViewHolder调用该方法获取对应的视图组件 * * @param resId * @param <T> * @return */ public <T extends View> T getView(int resId) { View view = mSparseArray.get(resId); if (view == null) { View mViewViewById = mView.findViewById(resId); mSparseArray.put(resId, mViewViewById); } return (T) view; } }
|
BaseRecycleAdapter
有了通用的BaseViewholder对于adapter就好写了,只要抽象一个数据绑定方法给外部使用,其他的都封装隐藏,如下所示:
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
|
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> { protected Context mContext; protected int mLayoutId; protected List<T> mData; public BaseRecyclerAdapter(Context context, int layoutId, List<T> data) { this.mContext = context; this.mLayoutId = layoutId; this.mData = data; } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder = BaseViewHolder.createViewHolder(mContext, mLayoutId, parent); return holder; } @Override public void onBindViewHolder(BaseViewHolder holder, int position) { convert(holder, position); } @Override public int getItemCount() { return mData.size(); } public abstract void convert(BaseViewHolder holder, int position); }
|
对于多类型的MultiItemRecyclerAdapter
在BaseRecycleAdapter基础上实现一个getItemViewType方法,有几种类型adapter是不知道了,只能通过实现接口由外部传入的数据决定,如下:
1 2 3 4
|
public interface MultiItemViewType<T> { int getLayoutId(int layoutId); int getViewType(int position, T t); }
|
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
|
public abstract class MultiItemRecyclerAdapter<T> extends BaseRecyclerAdapter<T> { protected Context mContext; protected List<T> mData; protected MultiItemViewType<T> mMultiItemViewType; public MultiItemRecyclerAdapter(Context context, List<T> data, MultiItemViewType<T> itemViewType) { super(context, -1, data); this.mContext = context; this.mData = data; this.mMultiItemViewType = itemViewType; } @Override public int getItemViewType(int position) { return mMultiItemViewType.getViewType(position, mData.get(position)); } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { int layoutId = mMultiItemViewType.getLayoutId(viewType); BaseViewHolder baseViewHolder = BaseViewHolder.createViewHolder(mContext, layoutId, parent); return baseViewHolder; } }
|
对应给RecyclerView添加头部和尾部都是相同原理
近期评论