天天看點

對base-adapter-helper的簡單分析

然後下載下傳看看,我等小菜也來分析分析。 

源代碼包括4個檔案: 

BaseAdapterHelper.java 

BaseQuickAdapter.java 

EnhancedQuickAdapter.java 

QuickAdapter.java 

其中最基本的是前兩個。

先看BaseAdapterHelper。第一個文章也寫了,這個類是替代viewHolder的。進一步封裝優化的産物,包括一些封裝好的經常使用功能,比方imageView圖檔的載入,文本框改動文本,給控件加入各種事件等等。 

先上代碼,凝視我自己加的:

<code></code>

<code>View.VISIBLE : View.GONE); return this; } //加入 addLinks public BaseAdapterHelper linkify(int viewId) { TextView view = retrieveView(viewId); Linkify.addLinks(view, Linkify.ALL); return this; } // 文本框字型 public BaseAdapterHelper setTypeface(int viewId, Typeface typeface) { TextView view = retrieveView(viewId); view.setTypeface(typeface); view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); return this; } public BaseAdapterHelper setTypeface(Typeface typeface, int... viewIds) { for (int viewId : viewIds) { TextView view = retrieveView(viewId); view.setTypeface(typeface); view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); } return this; } // 設定進度條 public BaseAdapterHelper setProgress(int viewId, int progress) { ProgressBar view = retrieveView(viewId); view.setProgress(progress); return this; } public BaseAdapterHelper setProgress(int viewId, int progress, int max) { ProgressBar view = retrieveView(viewId); view.setMax(max); view.setProgress(progress); return this; } public BaseAdapterHelper setMax(int viewId, int max) { ProgressBar view = retrieveView(viewId); view.setMax(max); return this; } public BaseAdapterHelper setRating(int viewId, float rating) { RatingBar view = retrieveView(viewId); view.setRating(rating); return this; } public BaseAdapterHelper setRating(int viewId, float rating, int max) { RatingBar view = retrieveView(viewId); view.setMax(max); view.setRating(rating); return this; } // 設定控件的點選事件 public BaseAdapterHelper setOnClickListener(int viewId, View.OnClickListener listener) { View view = retrieveView(viewId); view.setOnClickListener(listener); return this; } // 設定控件的onTouch事件 public BaseAdapterHelper setOnTouchListener(int viewId, View.OnTouchListener listener) { View view = retrieveView(viewId); view.setOnTouchListener(listener); return this; } public BaseAdapterHelper setOnLongClickListener(int viewId, View.OnLongClickListener listener) { View view = retrieveView(viewId); view.setOnLongClickListener(listener); return this; } // 設定控件的tag public BaseAdapterHelper setTag(int viewId, Object tag) { View view = retrieveView(viewId); view.setTag(tag); return this; } public BaseAdapterHelper setTag(int viewId, int key, Object tag) { View view = retrieveView(viewId); view.setTag(key, tag); return this; } // 設定選中狀态 public BaseAdapterHelper setChecked(int viewId, boolean checked) { Checkable view = (Checkable) retrieveView(viewId); view.setChecked(checked); return this; } // 設定adapter public BaseAdapterHelper setAdapter(int viewId, Adapter adapter) { AdapterView view = retrieveView(viewId); view.setAdapter(adapter); return this; } public View getView() { return convertView; } // 得到item的position,假設是-1,則異常 public int getPosition() { if (position == -1) throw new IllegalStateException("Use BaseAdapterHelper constructor " + "with position if you need to retrieve the position."); return position; } public Object getAssociatedObject() { return associatedObject; } /** Should be called during convert */ public void setAssociatedObject(Object associatedObject) { this.associatedObject = associatedObject; } }</code>

構造函數是一些初始化,convertView的載入。views的初始化。

看這個靜态方法,<code>static BaseAdapterHelper get(Context context, View convertView, ViewGroup parent, int layoutId, int position)</code>,能夠通過類名.的方式生成這個類的執行個體。傳入的convertView是listview的getView方法裡的。layoutId即為item的布局檔案id。 

<code>protected &lt;T extends View&gt; T retrieveView(int viewId)</code>這種方法替代了holderview的作用。 

後面的方法都是設定控件的屬性或者事件等等,注意associatedObject這個屬性是item的data,是以是Object類型。

再看看核心的BaseQuickAdapter。 

代碼:

<code>1 : 0; return data.size() + extra; } @Override public T getItem(int position) { if (position &gt;= data.size()) return null; return data.get(position); } @Override public long getItemId(int position) { return position; } // item type的數量,兩種,一種是item,都是同樣的,還有一種是Progress @Override public int getViewTypeCount() { return 2; } // 當position超過data數量時,載入progress,是還有一種布局 @Override public int getItemViewType(int position) { return position &gt;= data.size() ?</code>

<code>1 : 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (getItemViewType(position) == 0) {//普通布局 final H helper = getAdapterHelper(position, convertView, parent);//getAdapterHelper()是一個抽象方法,子類實作,須要提供的參數是layoutID,也就是item的布局 T item = getItem(position); helper.setAssociatedObject(item); convert(helper, item);//convert須要之類實作。功能邏輯 return helper.getView(); } return createIndeterminateProgressView(convertView, parent);//載入progress布局 } private View createIndeterminateProgressView(View convertView, ViewGroup parent) { if (convertView == null) { FrameLayout container = new FrameLayout(context); container.setForegroundGravity(Gravity.CENTER); ProgressBar progress = new ProgressBar(context); container.addView(progress); convertView = container; } return convertView; } @Override public boolean isEnabled(int position) { return position &lt; data.size(); } public void add(T elem) { data.add(elem); notifyDataSetChanged(); } public void addAll(List&lt;T&gt; elem) { data.addAll(elem); notifyDataSetChanged(); } public void set(T oldElem, T newElem) { set(data.indexOf(oldElem), newElem); } public void set(int index, T elem) { data.set(index, elem); notifyDataSetChanged(); } public void remove(T elem) { data.remove(elem); notifyDataSetChanged(); } public void remove(int index) { data.remove(index); notifyDataSetChanged(); } public void replaceAll(List&lt;T&gt; elem) { data.clear(); data.addAll(elem); notifyDataSetChanged(); } public boolean contains(T elem) { return data.contains(elem); } /** Clear data list */ public void clear() { data.clear(); notifyDataSetChanged(); } public void showIndeterminateProgress(boolean display) { if (display == displayIndeterminateProgress) return; displayIndeterminateProgress = display; notifyDataSetChanged(); } /** * Implement this method and use the helper to adapt the view to the given item. * @param helper A fully initialized helper. * @param item The item that needs to be displayed. */ protected abstract void convert(H helper, T item); /** * You can override this method to use a custom BaseAdapterHelper in order to fit your needs * @param position The position of the item within the adapter's data set of the item whose view we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view * is non-null and of an appropriate type before using. If it is not possible to convert * this view to display the correct data, this method can create a new view. * Heterogeneous lists can specify their number of view types, so that this View is * always of the right type (see {@link #getViewTypeCount()} and * {@link #getItemViewType(int)}). * @param parent The parent that this view will eventually be attached to * @return An instance of BaseAdapterHelper */ protected abstract H getAdapterHelper(int position, View convertView, ViewGroup parent); }</code>

這個類繼承了BaseAdapter,是抽象類,抽象方法為<code>protected abstract void convert(H helper, T item);</code>和<code>protected abstract H getAdapterHelper(int position, View convertView, ViewGroup parent);</code>供子類實作,convert是使用者須要實作的功能邏輯,getAdapterHelper須要使用者提供item的layoutId。

這個類設計的是包括兩種布局,一種是使用者自己定義的item布局,還有一種是Progress的布局,是以在getCount()傳回的是data.size()+1,getViewTypeCount()傳回2,區分這兩種用getItemViewType()。 

看最重要的getView()方法,首先依據getItemViewType()推斷類型,為0 就是item布局,通過調用子類的getAdapterHelper()方法得到對應的AdapterHelper進行設定。為1就是Progress。通過new了一個FrameLayout布局實作。在item生成過程中,convert()是最重要的。對于實際的開發,一般用于設定item圖檔載入、文本框設定文本等等相似邏輯。

大概重要的都說了,代碼凝視也有。在上面第一個提到的文章裡也說了,這個項目不支援item有多個布局,事實上我們能夠改動,那篇文章裡也有,詳細的就是添加一個布局數組,在getView()方法中加以推斷,比方聊天界面,有發送方和接收方。布局是左右相反的,一個是靠左。還有一個靠右,在消息類裡肯定有這個屬性,是否是自己發送。用這個項目其中來。就是重寫getItemViewType(),在getView()中推斷和載入。

努力學習和運用開源項目,了解後面的原理和流程,對自己思路和能力都有非常大提高,還要繼續學習。

本文轉自mfrbuaa部落格園部落格,原文連結:http://www.cnblogs.com/mfrbuaa/p/5173994.html,如需轉載請自行聯系原作者

繼續閱讀