recyclerview总结之apater封装

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添加头部和尾部都是相同原理