RecyclerView的通用適配器,和滾動時不加載圖片的封裝
摘要
本文原創,轉載請注明地址:http://kymjs.com/code/2015/10/11/01介紹一個通用的Adapter實現,和對RecyclerView滾動時不加載圖片的封裝。
很早之前寫過一篇講ListView的萬能適配器的方案通用Adapter與ListView滾動時不加載圖片的封裝,可以讓你在寫ListView的Adapter時只關注對控件設置內容,而不需要再去考慮ViewHolder、控件初始化、以及實現BaseAdapter的其他三個必須實現的函數。
對于RecyclerView我們需要使用RecyclerAdapter,使用方式與ListViewAdapter類似,具體代碼大家可以在網上搜索,這里就只教大家使用封裝后的簡潔RecyclerAdapter了。
核心代碼
首先我們來看一部分核心代碼:
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerHolder> {public BaseRecyclerAdapter(RecyclerView v, Collection<T> datas, int itemLayoutId) { //... } /** * Recycler適配器填充方法 * * @param holder viewholder * @param item javabean * @param isScrolling RecyclerView是否正在滾動 */ public abstract void convert(RecyclerHolder holder, T item, int position, boolean isScrolling); @Override public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(cxt); View root = inflater.inflate(mItemLayoutId, parent, false); return new RecyclerHolder(root); } @Override public void onBindViewHolder(RecyclerHolder holder, int position) { convert(holder, realDatas.get(position), position, isScrolling); holder.itemView.setOnClickListener(getOnClickListener(position)); } }</pre><br />
以及RecyclerHolder的代碼
public class RecyclerHolder extends RecyclerView.ViewHolder { private final SparseArray<View> mViews;public RecyclerHolder(View itemView) { super(itemView); //一般不會超過8個吧 this.mViews = new SparseArray<View>(8); } /** * 通過控件的Id獲取對于的控件,如果沒有則加入views */ public <T extends View> T getView(int viewId) { View view = mViews.get(viewId); if (view == null) { view = itemView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } /** * 為TextView設置字符串 */ public RecyclerHolder setText(int viewId, String text) { TextView view = getView(viewId); view.setText(text); return this; } /** * 為ImageView設置圖片 */ public RecyclerHolder setImageByUrl(KJBitmap bitmap, int viewId, String url) { bitmap.display(getView(viewId), url); return this; } }</pre><br />
實現原理
其實實現原理和我們之前講過的ListView通用適配器的實現原理是一致的。Google以及在RecyclerAdapter中規范了 Holder的應用,加入了onCreateViewHolder()和onBindViewHolder()方法分別來實現ViewHolder的創建和對Holder中的控件設置內容。
但是適配器寫多了以后我們就會發現,其實這兩個函數中寫的內容也是重復的,于是就有了RecyclerHolder這個我們自己封裝的Holder。
與平時我們自己實現的ViewHolder最大的不同在于,我們以前定義ViewHolder都是一個item里面要用哪個控件就定義哪個控件,而為了通用,我們抽出它們共同的部分————都是View。
但是我們還不知道我們的item中究竟會有多少個控件,所以這里我們再定義一個集合類,當然它也可以是一個Map(不能是List,因為我們還需要讀取這個View呢,如果是List,就不知道哪個View保存在List的哪個index了,而用map可以通過View的id來作為key讀取),這里我們依舊使用推薦的SparseArray,原因我們之前的通用ListView適配器中已經講過了,這里就不再多說了,只需要把它看成是一個性能更好的Map就行了。完整代碼
最后,還有一個細節大家可以在完整代碼中看到,就是我加入了滾動監聽與item點擊事件,這樣就可以很方便的在基類中實現RecyclerView滾動的時候不加載圖片,以及Google沒有提供的RecyclerView的item點擊事件了。
- 附上完整代碼的GitHub路徑:
完整的BaseRecyclerAdapter
完整的RecyclerHolder
以及實際使用Demo
</ul>
一點補充
有關滾動時不加載圖片,之前有人提起了說我沒有提到,這里就順帶講一下實現原理:
其實就是在我們我適配器中聲明一個全局的boolean變量用來保存此刻是否在滾動,然后通過給ListView或RecyclerView設置滾動監聽,然后在滾動監聽器的onScrollStateChanged()方法中給boolean值賦值,看是否在滾動。
這樣在我們使用這個適配器的時候,就可以根據滾動狀態的不同來判斷:比如正在滾動的時候就只顯示內存緩存的圖片,如果內存緩存中沒有就顯示一張默認圖片;而如果沒有在滾動就采用正常的圖片加載方案去加載網絡或者緩存中的圖片。