Android SimpleAdapter源码详解

  1. <span style=”font-family:SimHei;font-size:18px;”></span>

一直没认真看过android的源码,也不太敢看,稀里糊涂也敲了一年的代码,现在想好好学习了,就把常用的源码都看了一下,小伙伴们来涨姿势吧,有错误的地方,直接指出,我脸厚不怕丢人。来吧。

刚开始学android的时候我经常使用SimpleAdapter,但是后来经常用到的对象实体,SimpleAdapter也就不符合要求了,一直自己继承BaseAdapter,但是有的地方用SimpleAdapter还是比较方便的,一句话就搞定了,也不用写Adapter,所以来悄悄源码吧。
SimpleAdapter的初始化:

[java][/java] view plaincopyprint?

  1. <span style=”font-family:SimHei;font-size:18px;”></span>
[java][/java] view plaincopyprint?

  1. <span style=”font-family:SimHei;font-size:18px;”></span><pre name=”code” class=”java”>SimpleAdapter sAdapter=new SimpleAdapter(this, mList, R.layout.activity_main,new String[]{“name”,”pwd”},new int[]{R.id.tv_name,R.id.tv_pwd});</pre>
  2. <pre></pre>
  3. <pre name=”code” class=”java”><span style=”font-family:SimHei;font-size:18px;”>下面是android的源码,加了详细的注释,不用再多说:</span></pre><pre name=”code” class=”java”><span style=”font-family:SimHei;font-size:18px;”></span><pre name=”code” class=”java”>public class SimpleAdapter extends BaseAdapter implements Filterable {
  4.     private int[] mTo; // 指向布局里面控件的id 比如:R.id.btn
  5.     private String[] mFrom; // 数据来源,来自Map里面的key
  6.     private ViewBinder mViewBinder;// 接口类型,里面有个setViewValue方法,用于出现特殊类型控件比如:drawable的时候在外部初始化接口,实现具体方法
  7.     private List<? extends Map<String, ?>> mData;// 用List打包的Map数据源
  8.     private int mResource;// 布局
  9.     private int mDropDownResource;// 不知道干嘛用的,但是估计也是留给外部调用的
  10.     private LayoutInflater mInflater;// 这个大家都知道,LayoutInflater用来载入界面
  11.     private SimpleFilter mFilter;// 过滤器,一般用不到
  12.     private ArrayList<Map<String, ?>> mUnfilteredData;
  13.     // SimpleAdapter初始化,将传进了的参数都赋给本地的对应变量
  14.     public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
  15.             int resource, String[] from, int[] to) {
  16.         mData = data;
  17.         mResource = mDropDownResource = resource;
  18.         mFrom = from;
  19.         mTo = to;
  20.         mInflater = (LayoutInflater) context
  21.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  22.     }
  23.     /*
  24.      * ListView 针对每个item,要求 adapter “返回一个视图” (getView),
  25.      * 也就是说ListView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到ListView的长度,
  26.      * 然后根据这个长度,调用getView()一行一行的绘制ListView的每一项。如果你的getCount()返回值是0的话,
  27.      * 列表一行都不会显示,如果返回1,就只显示一行。返回几则显示几行。如果我们有几千几万甚至更多的item要显示怎么办?
  28.      * 为每个Item创建一个新的View?不可能!!!实际上Android早已经缓存了这些视图,大家可以看下下面这个截图来理解下,
  29.      * 这个图是解释ListView工作原理的最经典的图了大家可以收藏下,不懂的时候拿来看看,加深理解,
  30.      * 其实Android中有个叫做Recycler的构件
  31.      */
  32.     public int getCount() {
  33.         return mData.size();
  34.     }
  35.     public Object getItem(int position) {
  36.         return mData.get(position);
  37.     }
  38.     public long getItemId(int position) {
  39.         return position;
  40.     }
  41.     public View getView(int position, View convertView, ViewGroup parent) {
  42.         // 调用createViewFromResource来优化内存
  43.         return createViewFromResource(position, convertView, parent, mResource);
  44.     }
  45.     /*
  46.      * ListView的机制在这里再说一下,当第一个数据来getView的时候convertView肯定是null,
  47.      * 那么就用mInflater.inflate(resource, parent,
  48.      * false)给它初始化一个View,但是当一屏滑到底了,第一个item,滑出了屏幕,那么它将
  49.      * 从底部出来,那时候convertView就不为null,这个方法的好处就是当convertView不为null
  50.      * 的时候不用加载布局,直接使用convertView, 节省了一步,这也是所说的优化ListView的第一个步骤。
  51.      */
  52.     private View createViewFromResource(int position, View convertView,
  53.             ViewGroup parent, int resource) {
  54.         View v;
  55.         if (convertView == null) {
  56.             v = mInflater.inflate(resource, parent, false);
  57.         } else {
  58.             v = convertView;
  59.         }
  60.         // 这个方法是核心
  61.         bindView(position, v);
  62.         return v;
  63.     }
  64.     public void setDropDownViewResource(int resource) {
  65.         this.mDropDownResource = resource;
  66.     }
  67.     @Override
  68.     public View getDropDownView(int position, View convertView, ViewGroup parent) {
  69.         return createViewFromResource(position, convertView, parent,
  70.                 mDropDownResource);
  71.     }
  72.     // 这个方法的主要功能就是按照 to数组里面控件的顺序挨个赋值,比如new int[]{R.id.tv_name,R.id.tv_pwd}。
  73.     private void bindView(int position, View view) {
  74.         final Map dataSet = mData.get(position);// 找到对应的position位置的map数据
  75.         // 如果没找到跳出
  76.         if (dataSet == null) {
  77.             return;
  78.         }
  79.         /*
  80.          * 将外部实现的ViewBinder,赋值给本地,SimpleAdapter能够实现:
  81.          * checkBox,CheckedTextView,TextView
  82.          * ,ImageView,数据类型也就是Boolean,Integer,Stirng, 所以特殊数据类型的时候才用到ViewBinder
  83.          * ,如果没用到就不需要外部实现ViewBinder接口和里面的方法
  84.          */
  85.         final ViewBinder binder = mViewBinder;
  86.         final String[] from = mFrom;
  87.         final int[] to = mTo;
  88.         final int count = to.length;
  89. //view.findViewById(to[i]),循环找控件
  90.         for (int i = 0; i < count; i++) {
  91.             final View v = view.findViewById(to[i]);
  92.             //如果v不为空的话,找到对应的数据,Object类型的data转换为String,因为boolean在map里面纯的也是true或者false
  93.             if (v != null) {
  94.                 final Object data = dataSet.get(from[i]);
  95.                 String text = data == null ? “” : data.toString();
  96.                 if (text == null) {
  97.                     text = “”;
  98.                 }
  99. //标志变量bound,判断外部有没有实现ViewBinder,如果实现了,就执行binder.setViewValue(v, data, text),如果符合特殊条件,就返回true
  100.                 boolean bound = false;
  101.                 if (binder != null) {
  102.                     bound = binder.setViewValue(v, data, text);
  103.                 }
  104. //如果满足if (!bound)那么bound就还是false,说明是普通数据
  105.                 if (!bound) {
  106.                     //查看v是不是Checkable的实例化类型,满足的情况可能是CheckBox,CheckedTextView
  107.                     if (v instanceof Checkable) {
  108.                         //如果数据类型是boolean,那么就是CheckBox
  109.                         if (data instanceof Boolean) {
  110.                             ((Checkable) v).setChecked((Boolean) data);
  111.                             //如果不是CheckBox,那么判断是不是继承TextView的CheckedTextView,是的话赋值,不是就抛出异常
  112.                         } else if (v instanceof TextView) {
  113.                             setViewText((TextView) v, text);
  114.                         } else {
  115.                             throw new IllegalStateException(v.getClass()
  116.                                     .getName()
  117.                                     + ” should be bound to a Boolean, not a “
  118.                                     + (data == null ? “<unknown type>”
  119.                                             : data.getClass()));
  120.                         }
  121.                         //如果不是Checkable的实例化类型,判断是不是TextView的实例化类型
  122.                     } else if (v instanceof TextView) {
  123.                         setViewText((TextView) v, text);
  124.                         //都不是以上情况,就判断一下是不是ImageView的实例化类型
  125.                     } else if (v instanceof ImageView) {
  126.                         //这里只满足数据类型为int也就是R.drawable.ic,和String类型的url,如果想实现直接用drawbale,就要实现ViewBinder
  127.                         if (data instanceof Integer) {
  128.                             setViewImage((ImageView) v, (Integer) data);
  129.                         } else {
  130.                             setViewImage((ImageView) v, text);
  131.                         }
  132.                     } else {
  133.                         throw new IllegalStateException(
  134.                                 v.getClass().getName()
  135.                                         + ” is not a “
  136.                                         + ” view that can be bounds by this SimpleAdapter”);
  137.                     }
  138.                 }
  139.             }
  140.         }
  141.     }
  142.     public ViewBinder getViewBinder() {
  143.         return mViewBinder;
  144.     }
  145.     public void setViewBinder(ViewBinder viewBinder) {
  146.         mViewBinder = viewBinder;
  147.     }
  148.     public void setViewImage(ImageView v, int value) {
  149.         v.setImageResource(value);
  150.     }
  151.     public void setViewImage(ImageView v, String value) {
  152.         try {
  153.             v.setImageResource(Integer.parseInt(value));
  154.         } catch (NumberFormatException nfe) {
  155.             v.setImageURI(Uri.parse(value));
  156.         }
  157.     }
  158.     public void setViewText(TextView v, String text) {
  159.         v.setText(text);
  160.     }
  161.     public Filter getFilter() {
  162.         if (mFilter == null) {
  163.             mFilter = new SimpleFilter();
  164.         }
  165.         return mFilter;
  166.     }
  167.     public static interface ViewBinder {
  168.         boolean setViewValue(View view, Object data, String textRepresentation);
  169.     }
  170. //这个不知道干嘛用的,也没用过,好像是过滤数据的
  171.     private class SimpleFilter extends Filter {
  172.         @Override
  173.         protected FilterResults performFiltering(CharSequence prefix) {
  174.             FilterResults results = new FilterResults();
  175.             if (mUnfilteredData == null) {
  176.                 mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
  177.             }
  178.             if (prefix == null || prefix.length() == 0) {
  179.                 ArrayList<Map<String, ?>> list = mUnfilteredData;
  180.                 results.values = list;
  181.                 results.count = list.size();
  182.             } else {
  183.                 String prefixString = prefix.toString().toLowerCase();
  184.                 ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
  185.                 int count = unfilteredValues.size();
  186.                 ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(
  187.                         count);
  188.                 for (int i = 0; i < count; i++) {
  189.                     Map<String, ?> h = unfilteredValues.get(i);
  190.                     if (h != null) {
  191.                         int len = mTo.length;
  192.                         for (int j = 0; j < len; j++) {
  193.                             String str = (String) h.get(mFrom[j]);
  194.                             String[] words = str.split(” “);
  195.                             int wordCount = words.length;
  196.                             for (int k = 0; k < wordCount; k++) {
  197.                                 String word = words[k];
  198.                                 if (word.toLowerCase().startsWith(prefixString)) {
  199.                                     newValues.add(h);
  200.                                     break;
  201.                                 }
  202.                             }
  203.                         }
  204.                     }
  205.                 }
  206.                 results.values = newValues;
  207.                 results.count = newValues.size();
  208.             }
  209.             return results;
  210.         }
  211.         @Override
  212.         protected void publishResults(CharSequence constraint,
  213.                 FilterResults results) {
  214.             // noinspection unchecked
  215.             mData = (List<Map<String, ?>>) results.values;
  216.             if (results.count > 0) {
  217.                 notifyDataSetChanged();
  218.             } else {
  219.                 notifyDataSetInvalidated();
  220.             }
  221.         }
  222.     }
  223. }</pre><br>
  224. <strong><br>
  225. 最近在公司涨了很多姿势,大部分是Java的继承,接口,多态,抽象这些学过但是理解很肤浅的东西,以前自己写软件没什么规范,也没怎么去抽象,所以代码很不上档次,老鸟看到我的代码就笑话我,现在我准备好好学一下,希望自己有一天也能写出很正规的代码。</strong><pre name=”code” class=”java”></pre><pre name=”code” class=”java”></pre>
  226. <pre></pre>
  227. <pre></pre>
  228. </pre>

标签