很早以前寫過一篇講ListView的萬能適配器的方案通用Adapter與ListView滾動時不加載圖片的封裝,可讓你在寫ListView的Adapter時只關注對控件設置內容,而不須要再去考慮ViewHolder、控件初始化、以及實現BaseAdapter的其餘三個必須實現的函數。
對於RecyclerView咱們須要使用RecyclerAdapter,使用方式與ListViewAdapter相似,具體代碼你們能夠在網上搜索,這裏就只教你們使用封裝後的簡潔RecyclerAdapter了。java
##核心代碼 首先咱們來看一部分核心代碼:git
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)); } }
以及RecyclerHolder的代碼github
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; } }
##實現原理 其實實現原理和咱們以前講過的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點擊事件了。網絡
##一點補充
有關滾動時不加載圖片,以前有人提起了說我沒有提到,這裏就順帶講一下實現原理:
其實就是在咱們我適配器中聲明一個全局的boolean變量用來保存此刻是否在滾動,而後經過給ListView或RecyclerView設置滾動監聽,而後在滾動監聽器的onScrollStateChanged()方法中給boolean值賦值,看是否在滾動。
這樣在咱們使用這個適配器的時候,就能夠根據滾動狀態的不一樣來判斷:好比正在滾動的時候就只顯示內存緩存的圖片,若是內存緩存中沒有就顯示一張默認圖片;而若是沒有在滾動就採用正常的圖片加載方案去加載網絡或者緩存中的圖片。app