前情提要
最近项目我在项目中使用了RecyclerView代替了ListView.由于项目中有多出列表项使用RecyclerView,这就导致需要写多个Adapter和ViewHolder.
其实,怎么说呢?就是懒,想少写代码,所以想研究一下能否简化一下.
具体实现
封装分为Adapter和ViewHolder两部分,如下所示.
ViewHolder
抽象类BaseHolder继承RecyclerView.ViewHolder,并依赖注入的数据类型M,即和ViewHolder绑定的数据类型为M.
该抽象类包含一个构造方法,用于获取item对应的布局.一个抽象函数用于将数据设置到item上面.
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 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 abstract class BaseHolder
public BaseHolder(ViewGroup parent, @LayoutRes int resId) { super(LayoutInflater.from(parent.getContext()).inflate(resId, parent, false)); }
protected return (T) (itemView.findViewById(viewId)); }
protected Context getContext() { return itemView.getContext(); }
public abstract void setData(M data); } |
Adapter
Adapter类也为抽象类,继承于RecyclerView.Adapter,并绑定了两个泛型:
1. M : 用于该 Adapter 的列表的数据类型,即List
2. H : 即和 Adapter 绑定的 Holder 的类型.
并且,该 Adapter 自带 List 数据集合,声明时可以不用传递数据集合.也包含了 List 的相关操作.同时还给该 Adapter 绑定了一个 item 的点击事件,且为可选操作,不需要点击操作,直接传null即可.
[代码]java代码:
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
public abstract class BaseAdapter
protected List protected OnItemClickListener
public BaseAdapter(@Nullable List this.dataList = list; if (this.dataList == null) { this.dataList = new ArrayList(); }
this.listener = listener; }
@Override public void onBindViewHolder(final H holder, int position) { holder.setData(dataList.get(position)); if (listener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.onItemClick(holder); } }); } }
@Override public int getItemCount() { return dataList.size(); }
public void fillList(List dataList.clear(); dataList.addAll(list); }
public void updateItem(H holder, M data) { dataList.set(holder.getLayoutPosition(), data); }
public M getItem(H holder) { return dataList.get(holder.getLayoutPosition()); }
public M getItem(int position) { return dataList.get(position); }
public void appendItem(M data) { dataList.add(data); }
public void appendList(List dataList.addAll(list); }
public void preposeItem(M data) { dataList.add(0, data); }
public void preposeList(List dataList.addAll(0, list); } },> |
使用范例
使用范例为一种Item和多种Item这两种类型.
一种Item
运行结果如下图所示:
单个Item类型的ViewHolder如下:
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class SingleHolder extends BaseHolder
TextView nameView; TextView ageView;
public SingleHolder(ViewGroup parent, @LayoutRes int resId) { super(parent, resId);
nameView = getView(R.id.name_tv); ageView = getView(R.id.age_tv); }
@Override public void setData(Person data) { nameView.setText(data.getName()); ageView.setText(String.valueOf(data.getAge())); } } |
与之对应的Adapter如下:
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 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 |
public class SingleAdapter extends BaseAdapter
public SingleAdapter(SingleItemClickListener listener) { super(null, listener); }
@Override public SingleHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new SingleHolder(parent, R.layout.item_single); }
@Override public void onBindViewHolder(final SingleHolder holder, int position) { super.onBindViewHolder(holder, position); holder.nameView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ((SingleItemClickListener) listener).onNameClick(getItem(holder).getName()); } });
holder.ageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ((SingleItemClickListener) listener).onAgeClick(getItem(holder).getAge()); } }); }
public interface SingleItemClickListener extends OnItemClickListener
void onNameClick(String name);
void onAgeClick(int age); } },> |
多种Item
运行结果如下图所示:
多个Item的ViewHolder的写法,可以根据Item的View重合度来写:
1. 如果多个item完全没有相同的部分,则单独继承ViewHolder
2. 如果Item之间有相同的部分,可以抽出来一个父类来继承ViewHolder
这里的范例Item是具有重合部分的.模型来自聊天界面.
[代码]java代码:
|
1 2 3 4 5 6 7 8 9 |
Holder部分如下: |-ChatHolder //聊天View的Holder,包含公共部分 |-TextHolder //文字消息的Holder,包含文字特有的部分 |-ImageHolder //图片消息的Holder,包含图片特有的部分.
数据部分如下: |-ChatMsg //代表一条聊天消息 |-TextMsg //代表一条文字消息 |-ImageMsg //代表一条图片消息 |
ChatHolder代码如下,包含发送者的名称和时间:
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class ChatHolder extends BaseHolder
TextView senderNameTv; TextView createTimeTv;
public ChatHolder(ViewGroup parent, @LayoutRes int resId) { super(parent, resId);
senderNameTv = getView(R.id.name_tv); createTimeTv = getView(R.id.create_time_tv); }
@Override public void setData(ChatMsg data) { senderNameTv.setText(data.getSenderName()); createTimeTv.setText(data.getCreateTime()); } } |
TextHolder的代码如下,包含文本显示的View
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 |
public class TextHolder extends ChatHolder {
TextView contentTv;
public TextHolder(ViewGroup parent, @LayoutRes int resId) { super(parent, resId);
contentTv = getView(R.id.content_tv); }
@Override public void setData(ChatMsg data) { super.setData(data); contentTv.setText(((TextMsg)data).getText()); } } |
其中的setData()方法默认调用父类的方法,可以直接设置发送者的名称和时间.
ImageHolder的代码如下,包含显示图片的View
[代码]java代码:
|
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 |
public class ImageHolder extends ChatHolder {
ImageView contentIv;
public ImageHolder(ViewGroup parent, @LayoutRes int resId) { super(parent, resId); contentIv = getView(R.id.content_iv); }
@Override public void setData(ChatMsg data) { super.setData(data); contentIv.setImageResource(((ImageMsg)data).getResId()); } } |
最后是我们的Adapter,代码不多.
```java
public class ChatAdapter extends BaseAdapter
private static final int VIEW_TEXT = 0;
private static final int VIEW_IMAGE = 1;
public ChatAdapter(OnItemClickListener listener) {
super(null, listener);
}
@Override
public ChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ChatHolder holder;
if (viewType == VIEW_IMAGE) {
holder = new ImageHolder(parent, R.layout.item_msg_img_left);
} else {
holder = new TextHolder(parent, R.layout.item_msg_text_left);
}
return holder;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1868/viewspace-2814827/ ,如需转载,请注明出处,否则将追究法律责任。