对RecycleView-Adapter的简单封装

对分页展示而言,RecyclerView已经可以完全替代ListView。这里只进行一下对其Adapter的简单封装。至于RecyclerView的特性,会重开几篇博客来学习

分析

  • 目的:目的是为了减少Adapter具体实现的代码,使代码整洁,易于维护。
  • 分析:与listview面向view的adapter不同,recyclerview面向的是viewholder。所以BaseRecyclerAdapter需要两个泛型声明,一个是数据源,一个是viewholder。
    onCreateViewHoler()方法中需要生成具体的viewhoder实例,所以暂时不去对其做封装。对onBindViewHoler()方法的操作分为两步,一步是bindItemData()将数据填充至itemview,下一步是setupOnItemClick()设置每个item的点击监听。其它方法都是对便利性的扩展,可以根据不同情况添加。
  • 并没有对viewhoder动刀子,考虑到目前情况下在AS中利用ButterKnife可以高效的生成viewholder,对开发效率影响不大。不过ButterKnife毕竟是通过运行时反射对view进行绑定的,对效率是有影响,但是AS2.0之后发现Google有扶正DataBindding的趋势,所以综合考虑下,还是没有对viewholder动刀子。但是会在RecyclerView深入研究时思考这个问题。

BaseRecyclerViewAdapter

话不多说,上代码

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
61
62
63
64
65
66
67
68
public abstract class BaseRecyclerAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {

protected List<T> mDatas = new ArrayList<>();
protected Context mContext;
protected LayoutInflater inflater;
AdapterView.OnItemClickListener mItemClickListener;

public BaseRecyclerAdapter(List<T> mDatas, Context mContext) {
this.mDatas = mDatas;
this.mContext = mContext;
inflater = LayoutInflater.from(mContext);
}

@Override
public void onBindViewHolder(VH holder, int position) {
final T item = getItem(position);
bindItemData(holder, item, position);
setupOnItemClick(holder, position);
}

protected abstract void bindItemData(VH viewHolder, T data, int position);

protected void setupOnItemClick(final VH viewHolder, final int position) {
if (mItemClickListener != null) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
mItemClickListener.onItemClick(null, viewHolder.itemView, position, position);
}
});
}
}

@Override
public int getItemCount() {
return mDatas.size();
}

public T getItem(int position) {
position = Math.max(0, position);
return mDatas.get(position);
}

public List<T> getDataSource() {
return mDatas;
}

public void addData(List<T> newItems) {
if (newItems != null) {
mDatas.addAll(newItems);
notifyDataSetChanged();
}
}

public void updateListViewData(List<T> lists) {
mDatas.clear();
if (lists != null) {
mDatas.addAll(lists);
notifyDataSetChanged();
}
}

public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
this.mItemClickListener = listener;
}

}

使用

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
public class NotesAdapter extends BaseRecyclerAdapter<NoteItem, NotesAdapter.NotesViewHolder> {

public NotesAdapter(List<NoteItem> mDatas, Context mContext) {
super(mDatas, mContext);
}

@Override
public NotesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View contentView = LayoutInflater.from(mContext)
.inflate(R.layout.recycler_item_note, parent, false);
NotesViewHolder vh = new NotesViewHolder(contentView);
return vh;
}

@Override
protected void bindItemData(NotesViewHolder viewHolder, NoteItem data, int position) {
viewHolder.titleTxt.setText(data.getTitle());
viewHolder.timeTxt.setText(data.getCreatedTime());
viewHolder.tagTxt.setText(data.getTags().size() != 0 ? data.getTags().get(0) : "other");
}

static class NotesViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.title_txt)
TextView titleTxt;
@Bind(R.id.time_txt)
TextView timeTxt;
@Bind(R.id.tag_txt)
TextView tagTxt;

NotesViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}

}
}