<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## (一).前言: Base-Adater-Helper是對我們傳統的BaseAdapter的ViewHolder的模式的一個抽象封裝,主要的功能可以讓我們簡化的書寫AbsListView,例如ListView,GridView的自定義Adapter的代碼,上一篇我們已經對該項目的基本使用做了介紹實例,今天我們來對該項目的實現詳解源碼分析一下,同時我們可以對此框架進行擴展開發。 FastDev4Android框架項目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) 基本使用方式如下: ![](https://box.kancloud.cn/2016-01-18_569c8eb7ebc67.jpg) 我們看一下它的實例使用方法: ~~~ mAdapter = newQuickAdapter<ModuleBean>(this, R.layout.lv_item_base_layout,moduleBeans){ @Override protected voidconvert(BaseAdapterHelper helper, ModuleBean item) { //列表底下顯示進度 mAdapter.showIndeterminateProgress(true); helper.setText(R.id.text_lv_item_title, item.getModulename()) .setText(R.id.text_lv_item_description, item.getDescription()) .setImageUrl(R.id.img_lv_item, item.getImgurl()); } }; lv_base_adapter.setAdapter(mAdapter); ~~~ ## (二).總體分析: 整個項目其實比較簡單也就是四個主要的類: * BaseAdapterHelper * BaseQuickAdapter * EnhancedQuickAdapter * QuickAdapter 通過閱讀整個項目源代碼之后發現,當前實現也是基于ViewHolder模式的,等會我 們分析就知道了。其中view類型相關的采用泛型存儲,最重要的數據綁定工作,采用抽象函數convert()實現,全部交給用戶來實現自定義的綁定。 從上面的基本使用中發現,我們在使用該base-adapter-helper過程中,只需要創建newQuickAdapter()傳入布局,數據,控件和數據模型綁定即可。但是我們查看QuickAdapter類的代碼發現: ~~~ packagecom.chinaztt.fda.adapter.base; importandroid.content.Context; importandroid.view.View; importandroid.view.ViewGroup; importjava.util.List; import staticcom.chinaztt.fda.adapter.base.BaseAdapterHelper.get; /** * Abstraction class of a BaseAdapter in whichyou only need * to provide the convert()implementation.<br/> * Using the provided BaseAdapterHelper, yourcode is minimalist. * @param <T> The type of the items inthe list. */ public abstractclass QuickAdapter<T> extends BaseQuickAdapter<T,BaseAdapterHelper> { /** * Create a QuickAdapter. * @param context The context. * @param layoutResId The layout resourceid of each item. */ public QuickAdapter(Context context, intlayoutResId) { super(context, layoutResId); } /** * Same asQuickAdapter#QuickAdapter(Context,int) but with * some initialization data. * @param context The context. * @param layoutResId The layout resourceid of each item. * @param data A new list is created out of this oneto avoid mutable list */ public QuickAdapter(Context context, intlayoutResId, List<T> data) { super(context, layoutResId, data); } /** * 進行獲取類ViewHolder的 BaseAdapterHelper * @param position The position of the item within theadapter's data set of the item whose view we want. * @param convertView The old view toreuse, if possible. Note: You should check that this view * is non-null and of anappropriate type before using. If it is not possible to convert * this view to display thecorrect data, this method can create a new view. * Heterogeneous lists canspecify 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 eventuallybe attached to * @return */ protected BaseAdapterHelpergetAdapterHelper(int position, View convertView, ViewGroup parent) { return get(context, convertView,parent, layoutResId, position); } } ~~~ 其實它并沒有做什么其他更多的時候,就只有兩個構造方法,和一個獲取BaseAdapterHelper對象的方法。所以要研究該框架,我們只需要研究它的父類BaseQuickAdapter和BaseAdapterHelper類即可。最后簡單的看一下EnhancedQuickAdapter類。 2.1.BaseQuickAdapter類:該類繼承了BaseAdapter類,同時實現了BaseAdapter中通用的幾個抽象方法(也就是我們平時自定義Adapter需要實現的幾個方法),完成了Adapter要做的絕大多數操作以及對于Data操作的方法(不過個人趕腳用處不是特別大哈~個人見解)。該類還有兩個泛型數據,其中T代表數據,H針對BaseAdapterHelper。 ~~~ packagecom.chinaztt.fda.adapter.base; importandroid.content.Context; importandroid.view.Gravity; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.BaseAdapter; importandroid.widget.FrameLayout; importandroid.widget.ProgressBar; importjava.util.ArrayList; importjava.util.List; /** * Abstraction class of a BaseAdapter in whichyou only need * to provide the convert()implementation.<br/> * Using the provided BaseAdapterHelper, yourcode is minimalist. * @param <T> The type of the items inthe list. */ public abstractclass BaseQuickAdapter<T, H extends BaseAdapterHelper> extendsBaseAdapter { protected static final String TAG =BaseQuickAdapter.class.getSimpleName(); //上下文引用 protected final Context context; //需要顯示的布局id protected final int layoutResId; //需要顯示的數據 protected final List<T> data; //是否顯示進度 protected booleandisplayIndeterminateProgress = false; /** * Create a QuickAdapter. * @param context The context. * @param layoutResId The layout resourceid of each item. */ public BaseQuickAdapter(Context context,int layoutResId) { this(context, layoutResId, null); } /** * Same asQuickAdapter#QuickAdapter(Context,int) but with * some initialization data. * @param context The context. * @param layoutResId The layout resourceid of each item. * @param data A new list is created out of this oneto avoid mutable list */ public BaseQuickAdapter(Context context,int layoutResId, List<T> data) { this.data = data == null ? newArrayList<T>() : new ArrayList<T>(data); this.context = context; this.layoutResId = layoutResId; } /** * 判斷是否需要顯示進度,如果顯示 數量+1 * @return */ @Override public int getCount() { int extra =displayIndeterminateProgress ? 1 : 0; return data.size() + extra; } /** * 判斷索引是否大于等于數據長度,如果等于,最后一個item應該為進度,那么返回的數據對象為null即可 * @param position * @return */ @Override public T getItem(int position) { if (position >= data.size()) returnnull; return data.get(position); } @Override public long getItemId(int position) { return position; } /** * view類型返回2,這邊還需要顯示進度bar * @return */ @Override public int getViewTypeCount() { return 2; } /** * 進行判斷索引是不是已經大于等于數據的長度 * 如果超過或者等于數據的長度 返回1 * @param position * @return */ @Override public int getItemViewType(int position) { return position >= data.size() ? 1 :0; } @Override public View getView(int position, ViewconvertView, ViewGroup parent) { if (getItemViewType(position) == 0) { //獲取適配器helper --相當于獲取ViewHolder-BaseAdapterHelper final H helper =getAdapterHelper(position, convertView, parent); //獲取item model 數據 T item = getItem(position); //給子類QuickAdapter來進行實現,不過QuickAdapter也是抽象類,給具體創建的類進行實現 convert(helper, item); helper.setAssociatedObject(item); return helper.getView(); } //顯示進度 returncreateIndeterminateProgressView(convertView, parent); } /** * 創建進度條 顯示在view的結尾 * @param convertView * @param parent * @return */ private ViewcreateIndeterminateProgressView(View convertView, ViewGroup parent) { if (convertView == null) { FrameLayout container = newFrameLayout(context); container.setForegroundGravity(Gravity.CENTER); ProgressBar progress = newProgressBar(context); container.addView(progress); convertView = container; } return convertView; } @Override public boolean isEnabled(int position) { return position < data.size(); } //==================================================== //下面的方法基本封裝了操作集合相關的 //主要為新增add,設置set,移除remove以及替換,是否存在判斷 //===================================================== public void add(T elem) { data.add(elem); notifyDataSetChanged(); } public void addAll(List<T> 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<T> 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 voidshowIndeterminateProgress(boolean display) { if (display ==displayIndeterminateProgress) return; displayIndeterminateProgress = display; notifyDataSetChanged(); } /** * 實現該方法,讓用戶自己綁定控件和數據 * Implement this method and use the helperto adapt the view to the given item. * @param helper A fully initializedhelper. * @param item The item that needs to be displayed. */ protected abstract void convert(H helper, Titem); /** * You can override this method to use acustom BaseAdapterHelper in order to fit your needs * @param position The position of the item within theadapter's data set of the item whose view we want. * @param convertView The old view toreuse, if possible. Note: You should check that this view * is non-null and of anappropriate type before using. If it is not possible to convert * this view to display thecorrect data, this method can create a new view. * Heterogeneous lists canspecify 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 eventuallybe attached to * @return An instance of BaseAdapterHelper */ protected abstract H getAdapterHelper(intposition, View convertView, ViewGroup parent); } ~~~ 重點我們來看下這個類的相關實現: 2.1.1.成員變量context為獲取控件所需要的上下文,layoutResId為布局文件的id。其中data的類型是List的,由于這邊傳入的實體信息可能是不同類型的集合,所以這邊采用了泛型來進行定義了。 2.1.2.getViewTypeCount(),getItemViewType()這邊我們可以看源代碼第一個函數返回2,第二個函數會進行判斷返回position。因為base-adapter-helper已經實現的progressbar進度的顯示控制條。 2.1.3.然后是一些實現adapter都要實現的方法例如:getCount,getView,getItem,getItemId之類的方法,還有一些關于數據操作的方法。 2.1.4.重點看一下getView方法: ~~~ public ViewgetView(int position, View convertView, ViewGroup parent) { if (getItemViewType(position) == 0) { //獲取適配器helper --相當于獲取ViewHolder-BaseAdapterHelper final H helper =getAdapterHelper(position, convertView, parent); //獲取item model 數據 T item = getItem(position); //給子類QuickAdapter來進行實現,不過QuickAdapter也是抽象類,給具體創建的類進行實現 convert(helper, item); helper.setAssociatedObject(item); return helper.getView(); } //顯示進度 returncreateIndeterminateProgressView(convertView, parent); } ~~~ 重點地方已經注釋了,在這個方法中,會首先進行判斷getItemViewType(position)的值,如果返回值不等于0的時候,那就是說顯示底部的進度,其他的情況會正常加載view。此時通過抽象方法getAdapterHelper()來進行獲取一個BaseAdapterHelper。 該抽象方法的實現類是QuickAdapter: ~~~ /** * 進行獲取類ViewHolder的 BaseAdapterHelper * @param position The position of the item within theadapter's data set of the item whose view we want. * @param convertView The old view toreuse, if possible. Note: You should check that this view * is non-null and of anappropriate type before using. If it is not possible to convert * this view to display thecorrect data, this method can create a new view. * Heterogeneous lists canspecify 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 eventuallybe attached to * @return */ protected BaseAdapterHelpergetAdapterHelper(int position, View convertView, ViewGroup parent) { return get(context, convertView,parent, layoutResId, position); } ~~~ 其中又去調用BaseAdapterHelper的如下方法: ~~~ /** This method ispackage private and should only be used by QuickAdapter. */ /** * 進行獲取類ViewHolder的BaseAdapterHelper對象 * @param context 上下文引用 * @param convertView item view * @param parent 父控件view * @param layoutId 布局ID * @param position 索引 * @return */ static BaseAdapterHelper get(Contextcontext, View convertView, ViewGroup parent, int layoutId, int position) { if (convertView == null) { return newBaseAdapterHelper(context, parent, layoutId, position); } // Retrieve the existing helper andupdate its position BaseAdapterHelper existingHelper =(BaseAdapterHelper) convertView.getTag(); existingHelper.position = position; return existingHelper; } ~~~ 該類中的實現方法就是首先判斷convertView是否為null,如果為null,進行創建。否則直接從getTag()進行獲取,然后返回當前BaseAdapterHelper,到這邊相比大家有沒有明白BaseAdapterHelper和我們以前接觸的ViewHolder相似了呢?對的,這邊的BaseAdapterHelper其實就是充當的ViewHolder角色。 上面我們分析了getAdapterHelper的生成方式,下面我們看一下itemdata的獲取,這個比較簡單直接如下即可: //獲取item model數據? ?? ~~~ T item = getItem(position); ~~~ 該類最后我們來看一個最關鍵的代碼 //給子類QuickAdapter來進行實現,不過QuickAdapter也是抽象類,給具體創建的類進行實現 ~~~ convert(helper, item); ~~~ ???????????該convert()為抽象方法,convert的參數為BaseAdapterHelper和實體對象item,讓我們用戶可以自定義自由綁定數據到控件中。綁定成功之后直接通過調用helper.getView()返回即可。 2.2.BaseAdapterHelper類 上面get()方法的時候已經說過BaseAdapterHelper相當于ViewHolder,同時該類還提供一大堆的方法來讓我們進行設置view的數據,屬性,以及一些事件方法。?我們首先開看構造方法:????????? ~~~ protectedBaseAdapterHelper(Context context, ViewGroup parent, int layoutId, intposition) { this.context = context; this.position = position; this.views = newSparseArray<View>(); convertView =LayoutInflater.from(context) //根據布局id來加載view .inflate(layoutId, parent,false); convertView.setTag(this);//相當于存放ViewHolder } ~~~ 該構造方法創建一個稀疏數組來存放view對象(用來綁定數據的)。然后根據布局id來進行獲取convertView,同時把當前對象加入到convertView得tag中,然后后面我們可以通過convertView.getTag()來進行獲取,這樣保持BaseAdapterHelper對于convertView的相互持有引用。 除了以上的構造方法以外,還有另外一個進入BaseAdapterHelper的入口: ~~~ /** * This method is the only entry point toget a BaseAdapterHelper. * @param context The current context. * @param convertView The convertView argpassed to the getView() method. * @param parent The parent arg passed to the getView()method. * @return A BaseAdapterHelper instance. */ public static BaseAdapterHelper get(Contextcontext, View convertView, ViewGroup parent, int layoutId) { return get(context, convertView,parent, layoutId, -1); } /** This method is package private andshould only be used by QuickAdapter. */ /** * 進行獲取類ViewHolder的BaseAdapterHelper對象 * @param context 上下文引用 * @param convertView item view * @param parent 父控件view * @param layoutId 布局ID * @param position 索引 * @return */ static BaseAdapterHelper get(Contextcontext, View convertView, ViewGroup parent, int layoutId, int position) { if (convertView == null) { return newBaseAdapterHelper(context, parent, layoutId, position); } // Retrieve the existing helper andupdate its position BaseAdapterHelper existingHelper =(BaseAdapterHelper) convertView.getTag(); existingHelper.position = position; return existingHelper; } ~~~ 上面會進行判斷convertView是否存在,不存在進行調用構造方法創建,存在直接從convertView.getTag()來獲取BaseAdapterHelper對象。 下面我們來另外的比較重要的兩個方法,主要是獲取view控件,然后同時加入到稀疏數組中: ~~~ public <T extends View> T getView(intviewId) { return retrieveView(viewId); } ~~~ ~~~ /** * 進行從模板view中獲取相應的控件 然后放入到view控件集合中 */ protected <T extends View> TretrieveView(int viewId) { //從集合中獲取當前viewId的view,如果集合中不存在,那么從view重findById() //獲取出來存放到集合中 并且返回 View view = views.get(viewId); if (view == null) { view =convertView.findViewById(viewId); views.put(viewId, view); } return (T) view; } ~~~ 上面方法我們可以看出,每次調用retrieveView方法的時候,都會根據viewId去views集合中查詢一下,如果不存在,那么會通過findViewById(viewId)來進行獲取,同時把該view加入到集合中,這樣下次查詢就不需要重復調用findViewById()了。 其他一些工具方法,例如設置字體,文本,圖片,顏色,事件啊等等…. ![](https://box.kancloud.cn/2016-01-18_569c8eb81e568.jpg) 一大堆的方法這邊就不貼代碼了,具體每個方法的含義已經在項目源代碼中注釋了,大家有興趣可以去下載項目然后去閱讀一下: FastDev4Android框架項目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) 2.3.EnhancedQuickAdapter類:該類是繼承自QuickAdapter,其他多出下面的兩個方法: ~~~ /** * 進行綁定控件和數據 數據發生變化 * @param helper A fully initializedhelper. * @param item The item that needs to be displayed. */ @Override protected final voidconvert(BaseAdapterHelper helper, T item) { boolean itemChanged =helper.associatedObject == null || !helper.associatedObject.equals(item); helper.associatedObject = item; convert(helper, item, itemChanged); } /** * 讓用戶來自定義 * @param helper The helper to use to adapt the view. * @param item The item you should adapt the view to. * @param itemChanged Whether or not thehelper was bound to another object before. */ protected abstract voidconvert(BaseAdapterHelper helper, T item, boolean itemChanged); ~~~ 仔細看convert()方法,多了第三方參數itemChanged,對于data集合發生改變的時候刷新View。 ## (三).改進點: 我們在進行控件,數據模型進行綁定的時候都是采用set方法才完成。但是我們的需求是千變萬化的,就拿圖片加載來說,框架內部默認是采用Picasso來加載圖片的。但是如果我們的項目想要采用Volley,UIL或者Fresco呢?那么我們不得不需要在里邊進行擴展相應的方法來實現了。雖然這種方案可以解決問題,但是如果還有其他方案,那么一直在擴展就會變得很龐大了。幸運的時候convert()方法回調回來的BaseAdapterHelper對象helper,該類中有getView()和retrieveView()方法,同時getView()還是public,對外開放的,我們在convert()實現方法中直接通過getView()即可獲取view,然后如何顯示圖片就看我們自己的了。除此之外里邊很多設置字體,文本等等很少輔助類,如果需要設置更多的東西,我們需要不斷的擴展。 ## (四).結束語: 經過昨天和今天的講解介紹,相應大家對于base-adapter-helper的基本使用和源碼原理分析有一個比較清晰的了解,以后在項目中也可以多多使用這個,一定會提高寫代碼的效率。其他這個框架學習分析下來,非常核心的東西也還是比較好理解,重點要看思考,分析吧。繼續加油。 到此Base-Adapter-Helper的基本介紹和基本使用已經講完了,具體實例和框架注釋過的全部代碼已經上傳到FastDev4Android項目中了。 同時歡迎大家去Github站點進行clone或者下載瀏覽: [https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android)?同時歡迎大家star和fork整個開源快速開發框架項目~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看