Android RecyclerView中Adapter和ViewHo
前情提要
最近專案我在專案中使用了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部落格 ” ,連結:http://blog.itpub.net/1868/viewspace-2814827/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- RecyclerView的Adapter中attach和detach探索ViewAPT
- RecyclerView Adapter 系列(1):RecyclerView Array AdapterViewAPT
- RecyclerView Adapters 系列(2):RecyclerView Cursor AdapterViewAPT
- RecyclerView-->通用的AdapterViewAPT
- 為RecyclerView打造通用Adapter 讓RecyclerView更加好用ViewAPT
- RecyclerView 知識梳理(2) AdapterViewAPT
- RecyclerView.Adapter優化了嗎?ViewAPT優化
- Android中的RecyclerViewAndroidView
- 你還在用Adapter和ViewHolder寫RecyclerView嗎?Out了!APTView
- RecyclerView Adapter 優雅封裝,一個Adapter搞定所有列表ViewAPT封裝
- RecyclerView.Adapter的封裝(RecyclerAdapter)ViewAPT封裝
- Kotlin 打造一個RecyclerView的通用Adapter(一)KotlinViewAPT
- RecyclerView 之 Adapter 的簡化過程淺析ViewAPT
- 通過Data Binding為RecyclerView打造通用AdapterViewAPT
- Android中的RecyclerView: 基礎知識AndroidView
- Android RecyclerView的ViewHolder和AdaAndroidView
- Android 給RecyclerView新增頭部和尾部AndroidView
- 打造基於Databinding與RecyclerView的通用Adapter類ViewAPT
- MultiItem進階 實現Head Foot和載入更多-多型別RecyclerView Adapter多型型別ViewAPT
- Android中RecyclerView與Scrollview組合使用(二)AndroidView
- Android RecyclerView詳解AndroidView
- Android RecyclerView的使用AndroidView
- 在Android與recyclerview中使用列表和網格AndroidView
- 教你玩轉 Android RecyclerView:深入解析 RecyclerView ItemDecoration類AndroidView
- Android listview與adapter用法AndroidViewAPT
- 基於 Multitype 開源庫封裝更好用的RecyclerView.Adapter封裝ViewAPT
- 【Android Adapter】是時候開啟Adapter新時代了AndroidAPT
- android adapter getView方法中return null發生的異常AndroidAPTViewNull
- 說說在 Android 的 RecyclerView 中如何實現下拉刷AndroidView
- MultiItem用法與詳解-優雅的實現多型別RecyclerView Adapter多型型別ViewAPT
- (轉) Android 優雅的為RecyclerView新增HeaderView和FooterViewAndroidViewHeader
- Android開發之平板和橫豎屏適配-RecyclerViewAndroidView
- android adapter的效能小結AndroidAPT
- Android TV開發——RecyclerView For TVAndroidView
- Adapter中getView的理解!APTView
- RecyclerView基礎(一)Adapter與Holder的封裝之RvAdapter,RvHolderViewAPT封裝
- Android中利用ViewHolder優化自定義Adapter的典型寫法AndroidView優化APT
- 【Android進階】RecyclerView之ItemDecoration(一)AndroidView