Android之Adapter優化

做過Android開發的都知道,Adapter的使用頻率很高。無論是ListView、GridView、Gallery都需要設置Adapter,而且它們的Adapter幾乎一樣,讓我們來看看我們經常用到的Adapter吧,我們可以邊看邊思考到底有多少東西是我們經常需要重複的:

先從構造說起:LayoutInflater重複

  1. public MyAdapter1(Context context, int resId, List<String> data) {  
  2.         mData = data;  
  3.         mContext = context;  
  4.         mInflater = (LayoutInflater) context  
  5.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  6.         mLayoutResId = resId;  
  7.     }  
在說說其他需要重寫的方法:以下3個方法都是重複的寫(無任何技術含量)

  1. @Override  
  2.     public int getCount() {  
  3.         return mData.size();  
  4.     }  
  5.   
  6.     @Override  
  7.     public Object getItem(int arg0) {  
  8.         return mData.get(arg0);  
  9.     }  
  10.   
  11.     @Override  
  12.     public long getItemId(int arg0) {  
  13.         return arg0;  
  14.     }  

在看看最重要的getView方法:無非就是重用View,setTag (ViewHolder),除了ViewHolder的get和set內容不一樣其他都是在重複(傷不起有木有~!)。
  1. public View getView(int position, View view, ViewGroup viewgroup) {  
  2.     if (view == null) {  
  3.         mHolder = new ViewHolder();  
  4.         view = mInflater.inflate(mLayoutResId, null);  
  5.         mHolder.tvText = (TextView) view.findViewById(android.R.id.text1);  
  6.         view.setTag(mHolder);  
  7.     } else {  
  8.         mHolder = (ViewHolder) view.getTag();  
  9.     }  
  10.     mHolder.tvText.setText(mData.get(position).toString());  
  11.     return view;  
  12. }  
  13.   
  14. static class ViewHolder {  
  15.     TextView tvText;  
  16. }  
我們完全可以寫兩個基類把重複的東西抽取出來把代碼優化一下,看一下優化後的代碼吧:(在git看到的)
  1. package com.cym.chadtestdemo;  
  2.   
  3. import java.util.List;  
  4.   
  5. import android.content.Context;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8.   
  9. import com.chronocloud.lib.base.BaseAdapterHelper;  
  10. import com.chronocloud.lib.base.BaseQuickAdapter;  
  11.   
  12. /** 
  13.  *  
  14.  * @ClassName: MyAdapter 
  15.  * @Description: TODO 簡化後的Adapter 
  16.  * @author Chad.Cym 
  17.  * @date 2014年8月25日 下午8:22:31 
  18.  *  
  19.  * @param <T> 
  20.  */  
  21. public class MyAdapter<T> extends BaseQuickAdapter<T, BaseAdapterHelper> {  
  22.   
  23.     public MyAdapter(Context context, int layoutResId, List<T> data) {  
  24.         super(context, layoutResId, data);  
  25.     }  
  26.   
  27.     @Override  
  28.     protected void convert(BaseAdapterHelper helper, T item) {  
  29.         helper.setText(android.R.id.text1, item.toString());  
  30.     }  
  31.   
  32.     @Override  
  33.     protected BaseAdapterHelper getAdapterHelper(int position,  
  34.             View convertView, ViewGroup parent) {  
  35.   
  36.         return BaseAdapterHelper.get(context, convertView, parent, layoutResId);  
  37.     }  
  38.   
  39. }  
優化後只需要設置控件內容即可,不需要重複之前的所有重複代碼了。我們來看看抽取出來的基類:
  1. package com.chronocloud.lib.base;  
  2.   
  3. /** 
  4.  * 
  5.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  6.  * you may not use this file except in compliance with the License. 
  7.  * You may obtain a copy of the License at 
  8.  * 
  9.  *     http://www.apache.org/licenses/LICENSE-2.0 
  10.  * 
  11.  * Unless required by applicable law or agreed to in writing, software 
  12.  * distributed under the License is distributed on an "AS IS" BASIS, 
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14.  * See the License for the specific language governing permissions and 
  15.  * limitations under the License. 
  16.  */  
  17.   
  18. import com.nostra13.universalimageloader.core.DisplayImageOptions;  
  19. import com.nostra13.universalimageloader.core.ImageLoader;  
  20.   
  21. import android.content.Context;  
  22. import android.graphics.Bitmap;  
  23. import android.graphics.Paint;  
  24. import android.graphics.Typeface;  
  25. import android.graphics.drawable.Drawable;  
  26. import android.os.Build;  
  27. import android.text.util.Linkify;  
  28. import android.util.SparseArray;  
  29. import android.view.LayoutInflater;  
  30. import android.view.View;  
  31. import android.view.ViewGroup;  
  32. import android.view.animation.AlphaAnimation;  
  33. import android.widget.Adapter;  
  34. import android.widget.AdapterView;  
  35. import android.widget.Checkable;  
  36. import android.widget.CompoundButton;  
  37. import android.widget.ImageView;  
  38. import android.widget.ProgressBar;  
  39. import android.widget.RatingBar;  
  40. import android.widget.TextView;  
  41.   
  42. /** 
  43.  * Allows an abstraction of the ViewHolder pattern.<br> 
  44.  * <br> 
  45.  * <p/> 
  46.  * <b>Usage</b> 
  47.  * <p/> 
  48.  *  
  49.  * <pre> 
  50.  * return BaseAdapterHelper.get(context, convertView, parent, R.layout.item) 
  51.  *      .setText(R.id.tvName, contact.getName()) 
  52.  *      .setText(R.id.tvEmails, contact.getEmails().toString()) 
  53.  *      .setText(R.id.tvNumbers, contact.getNumbers().toString()).getView(); 
  54.  * </pre> 
  55.  */  
  56. public class BaseAdapterHelper {  
  57.   
  58.     /** Views indexed with their IDs */  
  59.     private final SparseArray<View> views;  
  60.   
  61.     private final Context context;  
  62.   
  63.     private int position;  
  64.   
  65.     private View convertView;  
  66.   
  67.     /** 
  68.      * Package private field to retain the associated user object and detect a 
  69.      * change 
  70.      */  
  71.     Object associatedObject;  
  72.   
  73.     private BaseAdapterHelper(Context context, ViewGroup parent, int layoutId,  
  74.             int position) {  
  75.         this.context = context;  
  76.         this.position = position;  
  77.         this.views = new SparseArray<View>();  
  78.         convertView = LayoutInflater.from(context) //  
  79.                 .inflate(layoutId, parent, false);  
  80.         convertView.setTag(this);  
  81.     }  
  82.   
  83.     /** 
  84.      * This method is the only entry point to get a BaseAdapterHelper. 
  85.      *  
  86.      * @param context 
  87.      *            The current context. 
  88.      * @param convertView 
  89.      *            The convertView arg passed to the getView() method. 
  90.      * @param parent 
  91.      *            The parent arg passed to the getView() method. 
  92.      * @return A BaseAdapterHelper instance. 
  93.      */  
  94.     public static BaseAdapterHelper get(Context context, View convertView,  
  95.             ViewGroup parent, int layoutId) {  
  96.         return get(context, convertView, parent, layoutId, -1);  
  97.     }  
  98.   
  99.     /** This method is package private and should only be used by QuickAdapter. */  
  100.     static BaseAdapterHelper get(Context context, View convertView,  
  101.             ViewGroup parent, int layoutId, int position) {  
  102.         if (convertView == null) {  
  103.             return new BaseAdapterHelper(context, parent, layoutId, position);  
  104.         }  
  105.   
  106.         // Retrieve the existing helper and update its position  
  107.         BaseAdapterHelper existingHelper = (BaseAdapterHelper) convertView  
  108.                 .getTag();  
  109.         existingHelper.position = position;  
  110.         return existingHelper;  
  111.     }  
  112.   
  113.     /** 
  114.      * This method allows you to retrieve a view and perform custom operations 
  115.      * on it, not covered by the BaseAdapterHelper.<br/> 
  116.      * If you think it's a common use case, please consider creating a new issue 
  117.      * at https://github.com/JoanZapata/base-adapter-helper/issues. 
  118.      *  
  119.      * @param viewId 
  120.      *            The id of the view you want to retrieve. 
  121.      */  
  122.     public <T extends View> T getView(int viewId) {  
  123.         return retrieveView(viewId);  
  124.     }  
  125.   
  126.     /** 
  127.      * Will set the text of a TextView. 
  128.      *  
  129.      * @param viewId 
  130.      *            The view id. 
  131.      * @param value 
  132.      *            The text to put in the text view. 
  133.      * @return The BaseAdapterHelper for chaining. 
  134.      */  
  135.     public BaseAdapterHelper setText(int viewId, String value) {  
  136.         TextView view = retrieveView(viewId);  
  137.         view.setText(value);  
  138.         return this;  
  139.     }  
  140.   
  141.     /** 
  142.      * Will set the image of an ImageView from a resource id. 
  143.      *  
  144.      * @param viewId 
  145.      *            The view id. 
  146.      * @param imageResId 
  147.      *            The image resource id. 
  148.      * @return The BaseAdapterHelper for chaining. 
  149.      */  
  150.     public BaseAdapterHelper setImageResource(int viewId, int imageResId) {  
  151.         ImageView view = retrieveView(viewId);  
  152.         view.setImageResource(imageResId);  
  153.         return this;  
  154.     }  
  155.   
  156.     /** 
  157.      * Will set background color of a view. 
  158.      *  
  159.      * @param viewId 
  160.      *            The view id. 
  161.      * @param color 
  162.      *            A color, not a resource id. 
  163.      * @return The BaseAdapterHelper for chaining. 
  164.      */  
  165.     public BaseAdapterHelper setBackgroundColor(int viewId, int color) {  
  166.         View view = retrieveView(viewId);  
  167.         view.setBackgroundColor(color);  
  168.         return this;  
  169.     }  
  170.   
  171.     /** 
  172.      * Will set background of a view. 
  173.      *  
  174.      * @param viewId 
  175.      *            The view id. 
  176.      * @param backgroundRes 
  177.      *            A resource to use as a background. 
  178.      * @return The BaseAdapterHelper for chaining. 
  179.      */  
  180.     public BaseAdapterHelper setBackgroundRes(int viewId, int backgroundRes) {  
  181.         View view = retrieveView(viewId);  
  182.         view.setBackgroundResource(backgroundRes);  
  183.         return this;  
  184.     }  
  185.   
  186.     /** 
  187.      * Will set text color of a TextView. 
  188.      *  
  189.      * @param viewId 
  190.      *            The view id. 
  191.      * @param textColor 
  192.      *            The text color (not a resource id). 
  193.      * @return The BaseAdapterHelper for chaining. 
  194.      */  
  195.     public BaseAdapterHelper setTextColor(int viewId, int textColor) {  
  196.         TextView view = retrieveView(viewId);  
  197.         view.setTextColor(textColor);  
  198.         return this;  
  199.     }  
  200.   
  201.     /** 
  202.      * Will set text color of a TextView. 
  203.      *  
  204.      * @param viewId 
  205.      *            The view id. 
  206.      * @param textColorRes 
  207.      *            The text color resource id. 
  208.      * @return The BaseAdapterHelper for chaining. 
  209.      */  
  210.     public BaseAdapterHelper setTextColorRes(int viewId, int textColorRes) {  
  211.         TextView view = retrieveView(viewId);  
  212.         view.setTextColor(context.getResources().getColor(textColorRes));  
  213.         return this;  
  214.     }  
  215.   
  216.     /** 
  217.      * Will set the image of an ImageView from a drawable. 
  218.      *  
  219.      * @param viewId 
  220.      *            The view id. 
  221.      * @param drawable 
  222.      *            The image drawable. 
  223.      * @return The BaseAdapterHelper for chaining. 
  224.      */  
  225.     public BaseAdapterHelper setImageDrawable(int viewId, Drawable drawable) {  
  226.         ImageView view = retrieveView(viewId);  
  227.         view.setImageDrawable(drawable);  
  228.         return this;  
  229.     }  
  230.   
  231.     /** 
  232.      * Will download an image from a URL and put it in an ImageView.<br/> 
  233.      * It uses Square's Picasso library to download the image asynchronously and 
  234.      * put the result into the ImageView.<br/> 
  235.      * Picasso manages recycling of views in a ListView.<br/> 
  236.      * If you need more control over the Picasso settings, use 
  237.      * {BaseAdapterHelper#setImageBuilder}. 
  238.      *  
  239.      * @param viewId 
  240.      *            The view id. 
  241.      * @param imageUrl 
  242.      *            The image URL. 
  243.      * @return The BaseAdapterHelper for chaining. 
  244.      */  
  245.     public BaseAdapterHelper setImageUrl(int viewId, String imageUrl) {  
  246.         ImageView view = retrieveView(viewId);  
  247.         ImageLoader.getInstance().displayImage(imageUrl, view);  
  248.         return this;  
  249.     }  
  250.   
  251.     public BaseAdapterHelper setImageUrl(int viewId, String imageUrl,  
  252.             DisplayImageOptions options) {  
  253.         ImageView view = retrieveView(viewId);  
  254.         ImageLoader.getInstance().displayImage(imageUrl, view, options);  
  255.         return this;  
  256.     }  
  257.   
  258.     /** 
  259.      * Add an action to set the image of an image view. Can be called multiple 
  260.      * times. 
  261.      */  
  262.     public BaseAdapterHelper setImageBitmap(int viewId, Bitmap bitmap) {  
  263.         ImageView view = retrieveView(viewId);  
  264.         view.setImageBitmap(bitmap);  
  265.         return this;  
  266.     }  
  267.   
  268.     /** 
  269.      * Add an action to set the alpha of a view. Can be called multiple times. 
  270.      * Alpha between 0-1. 
  271.      */  
  272.     public BaseAdapterHelper setAlpha(int viewId, float value) {  
  273.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {  
  274.             retrieveView(viewId).setAlpha(value);  
  275.         } else {  
  276.             // Pre-honeycomb hack to set Alpha value  
  277.             AlphaAnimation alpha = new AlphaAnimation(value, value);  
  278.             alpha.setDuration(0);  
  279.             alpha.setFillAfter(true);  
  280.             retrieveView(viewId).startAnimation(alpha);  
  281.         }  
  282.         return this;  
  283.     }  
  284.   
  285.     /** 
  286.      * Set a view visibility to VISIBLE (true) or GONE (false). 
  287.      *  
  288.      * @param viewId 
  289.      *            The view id. 
  290.      * @param visible 
  291.      *            True for VISIBLE, false for GONE. 
  292.      * @return The BaseAdapterHelper for chaining. 
  293.      */  
  294.     public BaseAdapterHelper setVisible(int viewId, boolean visible) {  
  295.         View view = retrieveView(viewId);  
  296.         view.setVisibility(visible ? View.VISIBLE : View.GONE);  
  297.         return this;  
  298.     }  
  299.   
  300.     /** 
  301.      * Add links into a TextView. 
  302.      *  
  303.      * @param viewId 
  304.      *            The id of the TextView to linkify. 
  305.      * @return The BaseAdapterHelper for chaining. 
  306.      */  
  307.     public BaseAdapterHelper linkify(int viewId) {  
  308.         TextView view = retrieveView(viewId);  
  309.         Linkify.addLinks(view, Linkify.ALL);  
  310.         return this;  
  311.     }  
  312.   
  313.     /** Apply the typeface to the given viewId, and enable subpixel rendering. */  
  314.     public BaseAdapterHelper setTypeface(int viewId, Typeface typeface) {  
  315.         TextView view = retrieveView(viewId);  
  316.         view.setTypeface(typeface);  
  317.         view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);  
  318.         return this;  
  319.     }  
  320.   
  321.     /** 
  322.      * Apply the typeface to all the given viewIds, and enable subpixel 
  323.      * rendering. 
  324.      */  
  325.     public BaseAdapterHelper setTypeface(Typeface typeface, int... viewIds) {  
  326.         for (int viewId : viewIds) {  
  327.             TextView view = retrieveView(viewId);  
  328.             view.setTypeface(typeface);  
  329.             view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);  
  330.         }  
  331.         return this;  
  332.     }  
  333.   
  334.     /** 
  335.      * Sets the progress of a ProgressBar. 
  336.      *  
  337.      * @param viewId 
  338.      *            The view id. 
  339.      * @param progress 
  340.      *            The progress. 
  341.      * @return The BaseAdapterHelper for chaining. 
  342.      */  
  343.     public BaseAdapterHelper setProgress(int viewId, int progress) {  
  344.         ProgressBar view = retrieveView(viewId);  
  345.         view.setProgress(progress);  
  346.         return this;  
  347.     }  
  348.   
  349.     /** 
  350.      * Sets the progress and max of a ProgressBar. 
  351.      *  
  352.      * @param viewId 
  353.      *            The view id. 
  354.      * @param progress 
  355.      *            The progress. 
  356.      * @param max 
  357.      *            The max value of a ProgressBar. 
  358.      * @return The BaseAdapterHelper for chaining. 
  359.      */  
  360.     public BaseAdapterHelper setProgress(int viewId, int progress, int max) {  
  361.         ProgressBar view = retrieveView(viewId);  
  362.         view.setMax(max);  
  363.         view.setProgress(progress);  
  364.         return this;  
  365.     }  
  366.   
  367.     /** 
  368.      * Sets the range of a ProgressBar to 0...max. 
  369.      *  
  370.      * @param viewId 
  371.      *            The view id. 
  372.      * @param max 
  373.      *            The max value of a ProgressBar. 
  374.      * @return The BaseAdapterHelper for chaining. 
  375.      */  
  376.     public BaseAdapterHelper setMax(int viewId, int max) {  
  377.         ProgressBar view = retrieveView(viewId);  
  378.         view.setMax(max);  
  379.         return this;  
  380.     }  
  381.   
  382.     /** 
  383.      * Sets the rating (the number of stars filled) of a RatingBar. 
  384.      *  
  385.      * @param viewId 
  386.      *            The view id. 
  387.      * @param rating 
  388.      *            The rating. 
  389.      * @return The BaseAdapterHelper for chaining. 
  390.      */  
  391.     public BaseAdapterHelper setRating(int viewId, float rating) {  
  392.         RatingBar view = retrieveView(viewId);  
  393.         view.setRating(rating);  
  394.         return this;  
  395.     }  
  396.   
  397.     /** 
  398.      * Sets the rating (the number of stars filled) and max of a RatingBar. 
  399.      *  
  400.      * @param viewId 
  401.      *            The view id. 
  402.      * @param rating 
  403.      *            The rating. 
  404.      * @param max 
  405.      *            The range of the RatingBar to 0...max. 
  406.      * @return The BaseAdapterHelper for chaining. 
  407.      */  
  408.     public BaseAdapterHelper setRating(int viewId, float rating, int max) {  
  409.         RatingBar view = retrieveView(viewId);  
  410.         view.setMax(max);  
  411.         view.setRating(rating);  
  412.         return this;  
  413.     }  
  414.   
  415.     /** 
  416.      * Sets the on click listener of the view. 
  417.      *  
  418.      * @param viewId 
  419.      *            The view id. 
  420.      * @param listener 
  421.      *            The on click listener; 
  422.      * @return The BaseAdapterHelper for chaining. 
  423.      */  
  424.     public BaseAdapterHelper setOnClickListener(int viewId,  
  425.             View.OnClickListener listener) {  
  426.         View view = retrieveView(viewId);  
  427.         view.setOnClickListener(listener);  
  428.         return this;  
  429.     }  
  430.   
  431.     /** 
  432.      * Sets the on touch listener of the view. 
  433.      *  
  434.      * @param viewId 
  435.      *            The view id. 
  436.      * @param listener 
  437.      *            The on touch listener; 
  438.      * @return The BaseAdapterHelper for chaining. 
  439.      */  
  440.     public BaseAdapterHelper setOnTouchListener(int viewId,  
  441.             View.OnTouchListener listener) {  
  442.         View view = retrieveView(viewId);  
  443.         view.setOnTouchListener(listener);  
  444.         return this;  
  445.     }  
  446.   
  447.     /** 
  448.      * Sets the on long click listener of the view. 
  449.      *  
  450.      * @param viewId 
  451.      *            The view id. 
  452.      * @param listener 
  453.      *            The on long click listener; 
  454.      * @return The BaseAdapterHelper for chaining. 
  455.      */  
  456.     public BaseAdapterHelper setOnLongClickListener(int viewId,  
  457.             View.OnLongClickListener listener) {  
  458.         View view = retrieveView(viewId);  
  459.         view.setOnLongClickListener(listener);  
  460.         return this;  
  461.     }  
  462.   
  463.     /** 
  464.      * Sets the tag of the view. 
  465.      *  
  466.      * @param viewId 
  467.      *            The view id. 
  468.      * @param tag 
  469.      *            The tag; 
  470.      * @return The BaseAdapterHelper for chaining. 
  471.      */  
  472.     public BaseAdapterHelper setTag(int viewId, Object tag) {  
  473.         View view = retrieveView(viewId);  
  474.         view.setTag(tag);  
  475.         return this;  
  476.     }  
  477.   
  478.     /** 
  479.      * Sets the tag of the view. 
  480.      *  
  481.      * @param viewId 
  482.      *            The view id. 
  483.      * @param key 
  484.      *            The key of tag; 
  485.      * @param tag 
  486.      *            The tag; 
  487.      * @return The BaseAdapterHelper for chaining. 
  488.      */  
  489.     public BaseAdapterHelper setTag(int viewId, int key, Object tag) {  
  490.         View view = retrieveView(viewId);  
  491.         view.setTag(key, tag);  
  492.         return this;  
  493.     }  
  494.   
  495.     /** 
  496.      * Sets the checked status of a checkable. 
  497.      *  
  498.      * @param viewId 
  499.      *            The view id. 
  500.      * @param checked 
  501.      *            The checked status; 
  502.      * @return The BaseAdapterHelper for chaining. 
  503.      */  
  504.     public BaseAdapterHelper setChecked(int viewId, boolean checked) {  
  505.         Checkable view = (Checkable) retrieveView(viewId);  
  506.         view.setChecked(checked);  
  507.         return this;  
  508.     }  
  509.   
  510.     /** 
  511.      * Sets the adapter of a adapter view. 
  512.      *  
  513.      * @param viewId 
  514.      *            The view id. 
  515.      * @param adapter 
  516.      *            The adapter; 
  517.      * @return The BaseAdapterHelper for chaining. 
  518.      */  
  519.     public BaseAdapterHelper setAdapter(int viewId, Adapter adapter) {  
  520.         AdapterView view = retrieveView(viewId);  
  521.         view.setAdapter(adapter);  
  522.         return this;  
  523.     }  
  524.   
  525.     /** Retrieve the convertView */  
  526.     public View getView() {  
  527.         return convertView;  
  528.     }  
  529.   
  530.     /** 
  531.      * Retrieve the overall position of the data in the list. 
  532.      *  
  533.      * @throws IllegalArgumentException 
  534.      *             If the position hasn't been set at the construction of the 
  535.      *             this helper. 
  536.      */  
  537.     public int getPosition() {  
  538.         if (position == -1)  
  539.             throw new IllegalStateException(  
  540.                     "Use BaseAdapterHelper constructor "  
  541.                             + "with position if you need to retrieve the position.");  
  542.         return position;  
  543.     }  
  544.   
  545.     @SuppressWarnings("unchecked")  
  546.     private <T extends View> T retrieveView(int viewId) {  
  547.         View view = views.get(viewId);  
  548.         if (view == null) {  
  549.             view = convertView.findViewById(viewId);  
  550.             views.put(viewId, view);  
  551.         }  
  552.         return (T) view;  
  553.     }  
  554.   
  555. }  

  1. package com.chronocloud.lib.base;  
  2.   
  3.   
  4. /** 
  5.  * Copyright 2013 Joan Zapata 
  6.  * 
  7.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  8.  * you may not use this file except in compliance with the License. 
  9.  * You may obtain a copy of the License at 
  10.  * 
  11.  *     http://www.apache.org/licenses/LICENSE-2.0 
  12.  * 
  13.  * Unless required by applicable law or agreed to in writing, software 
  14.  * distributed under the License is distributed on an "AS IS" BASIS, 
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  16.  * See the License for the specific language governing permissions and 
  17.  * limitations under the License. 
  18.  */  
  19.   
  20. import android.content.Context;  
  21. import android.view.Gravity;  
  22. import android.view.View;  
  23. import android.view.ViewGroup;  
  24. import android.widget.BaseAdapter;  
  25. import android.widget.FrameLayout;  
  26. import android.widget.ProgressBar;  
  27.   
  28. import java.util.ArrayList;  
  29. import java.util.List;  
  30.   
  31. /** 
  32.  * Abstraction class of a BaseAdapter in which you only need 
  33.  * to provide the convert() implementation.<br/> 
  34.  * Using the provided BaseAdapterHelper, your code is minimalist. 
  35.  * @param <T> The type of the items in the list. 
  36.  */  
  37. public abstract class BaseQuickAdapter<T, H extends BaseAdapterHelper> extends BaseAdapter {  
  38.   
  39.     protected static final String TAG = BaseQuickAdapter.class.getSimpleName();  
  40.   
  41.     protected final Context context;  
  42.   
  43.     protected final int layoutResId;  
  44.   
  45.     protected final List<T> data;  
  46.   
  47.     protected boolean displayIndeterminateProgress = false;  
  48.   
  49.     /** 
  50.      * Create a QuickAdapter. 
  51.      * @param context     The context. 
  52.      * @param layoutResId The layout resource id of each item. 
  53.      */  
  54.     public BaseQuickAdapter(Context context, int layoutResId) {  
  55.         this(context, layoutResId, null);  
  56.     }  
  57.   
  58.     /** 
  59.      * Same as QuickAdapter#QuickAdapter(Context,int) but with 
  60.      * some initialization data. 
  61.      * @param context     The context. 
  62.      * @param layoutResId The layout resource id of each item. 
  63.      * @param data        A new list is created out of this one to avoid mutable list 
  64.      */  
  65.     public BaseQuickAdapter(Context context, int layoutResId, List<T> data) {  
  66.         this.data = data == null ? new ArrayList<T>() : new ArrayList<T>(data);  
  67.         this.context = context;  
  68.         this.layoutResId = layoutResId;  
  69.     }  
  70.   
  71.     @Override  
  72.     public int getCount() {  
  73.         int extra = displayIndeterminateProgress ? 1 : 0;  
  74.         return data.size() + extra;  
  75.     }  
  76.   
  77.     @Override  
  78.     public T getItem(int position) {  
  79.         if (position >= data.size()) return null;  
  80.         return data.get(position);  
  81.     }  
  82.   
  83.     @Override  
  84.     public long getItemId(int position) {  
  85.         return position;  
  86.     }  
  87.   
  88.     @Override  
  89.     public int getViewTypeCount() {  
  90.         return 2;  
  91.     }  
  92.   
  93.     @Override  
  94.     public int getItemViewType(int position) {  
  95.         return position >= data.size() ? 1 : 0;  
  96.     }  
  97.   
  98.     @Override  
  99.     public View getView(int position, View convertView, ViewGroup parent) {  
  100.         if (getItemViewType(position) == 0) {  
  101.             final H helper = getAdapterHelper(position, convertView, parent);  
  102.             convert(helper, getItem(position));  
  103.             return helper.getView();  
  104.         }  
  105.   
  106.         return createIndeterminateProgressView(convertView, parent);  
  107.     }  
  108.   
  109.     private View createIndeterminateProgressView(View convertView, ViewGroup parent) {  
  110.         if (convertView == null) {  
  111.             FrameLayout container = new FrameLayout(context);  
  112.             container.setForegroundGravity(Gravity.CENTER);  
  113.             ProgressBar progress = new ProgressBar(context);  
  114.             container.addView(progress);  
  115.             convertView = container;  
  116.         }  
  117.         return convertView;  
  118.     }  
  119.   
  120.     @Override  
  121.     public boolean isEnabled(int position) {  
  122.         return position < data.size();  
  123.     }  
  124.   
  125.     public void add(T elem) {  
  126.         data.add(elem);  
  127.         notifyDataSetChanged();  
  128.     }  
  129.   
  130.     public void addAll(List<T> elem) {  
  131.         data.addAll(elem);  
  132.         notifyDataSetChanged();  
  133.     }  
  134.   
  135.     public void set(T oldElem, T newElem) {  
  136.         set(data.indexOf(oldElem), newElem);  
  137.     }  
  138.   
  139.     public void set(int index, T elem) {  
  140.         data.set(index, elem);  
  141.         notifyDataSetChanged();  
  142.     }  
  143.   
  144.     public void remove(T elem) {  
  145.         data.remove(elem);  
  146.         notifyDataSetChanged();  
  147.     }  
  148.   
  149.     public void remove(int index) {  
  150.         data.remove(index);  
  151.         notifyDataSetChanged();  
  152.     }  
  153.   
  154.     public void replaceAll(List<T> elem) {  
  155.         data.clear();  
  156.         data.addAll(elem);  
  157.         notifyDataSetChanged();  
  158.     }  
  159.   
  160.     public boolean contains(T elem) {  
  161.         return data.contains(elem);  
  162.     }  
  163.   
  164.     /** Clear data list */  
  165.     public void clear() {  
  166.         data.clear();  
  167.         notifyDataSetChanged();  
  168.     }  
  169.   
  170.     public void showIndeterminateProgress(boolean display) {  
  171.         if (display == displayIndeterminateProgress) return;  
  172.         displayIndeterminateProgress = display;  
  173.         notifyDataSetChanged();  
  174.     }  
  175.   
  176.     /** 
  177.      * Implement this method and use the helper to adapt the view to the given item. 
  178.      * @param helper A fully initialized helper. 
  179.      * @param item   The item that needs to be displayed. 
  180.      */  
  181.     protected abstract void convert(H helper, T item);  
  182.   
  183.     /** 
  184.      * You can override this method to use a custom BaseAdapterHelper in order to fit your needs 
  185.      * 
  186.      * @param position The position of the item within the adapter's data set of the item whose view we want. 
  187.      * @param convertView The old view to reuse, if possible. Note: You should check that this view 
  188.      *        is non-null and of an appropriate type before using. If it is not possible to convert 
  189.      *        this view to display the correct data, this method can create a new view. 
  190.      *        Heterogeneous lists can specify their number of view types, so that this View is 
  191.      *        always of the right type (see {@link #getViewTypeCount()} and 
  192.      *        {@link #getItemViewType(int)}). 
  193.      * @param parent The parent that this view will eventually be attached to 
  194.      * @return An instance of BaseAdapterHelper 
  195.      */  
  196.     protected abstract H getAdapterHelper(int position, View convertView, ViewGroup parent);  
  197.   

  1. }  
  2. 效果很明顯,簡單多了吧,希望能對大家有幫助。
    源碼地址:https://github.com/JoanZapata/base-adapter-helper 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章