Android SimpleAdapter源码详解

一直没认真看过android的源码,也不太敢看,稀里糊涂也敲了一年的代码,现在想好好学习了,就把常用的源码都看了一下,小伙伴们来涨姿势吧,有错误的地方,直接指出,我脸厚不怕丢人。来吧。
刚开始学android的时候我经常使用SimpleAdapter,但是后来经常用到的对象实体,SimpleAdapter也就不符合要求了,一直自己继承BaseAdapter,但是有的地方用SimpleAdapter还是比较方便的,一句话就搞定了,也不用写Adapter,所以来悄悄源码吧。
SimpleAdapter的初始化:

SimpleAdapter sAdapter=new SimpleAdapter(this, mList, R.layout.activity_main,new String[]{"name","pwd"},new int[]{R.id.tv_name,R.id.tv_pwd});

下面是android的源码,加了详细的注释,不用再多说:

public class SimpleAdapter extends BaseAdapter implements Filterable

{    

                  private int[] mTo; // 指向布局里面控件的id 比如:R.id.btn    

                  private String[] mFrom; // 数据来源,来自Map里面的key  

                  private ViewBinder mViewBinder;// 接口类型,里面有个setViewValue方法,用于出现特殊类型控件比如:drawable的时候在外部初始化接口,实现具体方法     

                  private List<? extends Map<String, ?>> mData;// 用List打包的Map数据源     

                  private int mResource;// 布局  

                  private int mDropDownResource;// 不知道干嘛用的,但是估计也是留给外部调用的  

                  private LayoutInflater mInflater;// 这个大家都知道,LayoutInflater用来载入界面     

                  private SimpleFilter mFilter;// 过滤器,一般用不到    

                  private ArrayList<Map<String, ?>> mUnfilteredData;     // SimpleAdapter初始化,将传进了的参数都赋给本地的对应变量  

                  public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,            int resource, String[] from, int[] to

        {      

                      mData = data;        mResource = mDropDownResource = resource;        mFrom = from;        mTo = to;        mInflater = (LayoutInflater) context                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);    }     /*     * ListView 针对每个item,要求 adapter “返回一个视图” (getView),     * 也就是说ListView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到ListView的长度,     * 然后根据这个长度,调用getView()一行一行的绘制ListView的每一项。如果你的getCount()返回值是0的话,     * 列表一行都不会显示,如果返回1,就只显示一行。返回几则显示几行。如果我们有几千几万甚至更多的item要显示怎么办?     * 为每个Item创建一个新的View?不可能!!!实际上Android早已经缓存了这些视图,大家可以看下下面这个截图来理解下,     * 这个图是解释ListView工作原理的最经典的图了大家可以收藏下,不懂的时候拿来看看,加深理解,     * 其实Android中有个叫做Recycler的构件     */    public int getCount() {        return mData.size();    }     public Object getItem(int position) {        return mData.get(position);    }     public long getItemId(int position) {        return position;    }     public View getView(int position, View convertView, ViewGroup parent) {        // 调用createViewFromResource来优化内存        return createViewFromResource(position, convertView, parent, mResource);    }     /*     * ListView的机制在这里再说一下,当第一个数据来getView的时候convertView肯定是null,     * 那么就用mInflater.inflate(resource, parent,     * false)给它初始化一个View,但是当一屏滑到底了,第一个item,滑出了屏幕,那么它将     * 从底部出来,那时候convertView就不为null,这个方法的好处就是当convertView不为null     * 的时候不用加载布局,直接使用convertView, 节省了一步,这也是所说的优化ListView的第一个步骤。     */    private View createViewFromResource(int position, View convertView,            ViewGroup parent, int resource) {        View v;        if (convertView == null) {            v = mInflater.inflate(resource, parent, false);        } else {            v = convertView;        }        // 这个方法是核心        bindView(position, v);         return v;    }     public void setDropDownViewResource(int resource) {        this.mDropDownResource = resource;    }     @Override    public View getDropDownView(int position, View convertView, ViewGroup parent) {        return createViewFromResource(position, convertView, parent,                mDropDownResource);    }     // 这个方法的主要功能就是按照 to数组里面控件的顺序挨个赋值,比如new int[]{R.id.tv_name,R.id.tv_pwd}。    private void bindView(int position, View view) {        final Map dataSet = mData.get(position);// 找到对应的position位置的map数据        // 如果没找到跳出        if (dataSet == null) {            return;        }        /*         * 将外部实现的ViewBinder,赋值给本地,SimpleAdapter能够实现:         * checkBox,CheckedTextView,TextView         * ,ImageView,数据类型也就是Boolean,Integer,Stirng, 所以特殊数据类型的时候才用到ViewBinder         * ,如果没用到就不需要外部实现ViewBinder接口和里面的方法         */        final ViewBinder binder = mViewBinder;        final String[] from = mFrom;        final int[] to = mTo;        final int count = to.length;//view.findViewById(to[i]),循环找控件        for (int i = 0; i < count; i++) {            final View v = view.findViewById(to[i]);            //如果v不为空的话,找到对应的数据,Object类型的data转换为String,因为boolean在map里面纯的也是true或者false            if (v != null) {                final Object data = dataSet.get(from[i]);                String text = data == null ? "" : data.toString();                if (text == null) {                    text = "";                }//标志变量bound,判断外部有没有实现ViewBinder,如果实现了,就执行binder.setViewValue(v, data, text),如果符合特殊条件,就返回true                boolean bound = false;                if (binder != null) {                    bound = binder.setViewValue(v, data, text);                }//如果满足if (!bound)那么bound就还是false,说明是普通数据                if (!bound) {                    //查看v是不是Checkable的实例化类型,满足的情况可能是CheckBox,CheckedTextView                    if (v instanceof Checkable) {                        //如果数据类型是boolean,那么就是CheckBox                        if (data instanceof Boolean) {                            ((Checkable) v).setChecked((Boolean) data);                            //如果不是CheckBox,那么判断是不是继承TextView的CheckedTextView,是的话赋值,不是就抛出异常                        } else if (v instanceof TextView) {                            setViewText((TextView) v, text);                        } else {                            throw new IllegalStateException(v.getClass()                                    .getName()                                    + " should be bound to a Boolean, not a "                                    + (data == null ? "<unknown type>"                                            : data.getClass()));                        }                        //如果不是Checkable的实例化类型,判断是不是TextView的实例化类型                    } else if (v instanceof TextView) {                        setViewText((TextView) v, text);                        //都不是以上情况,就判断一下是不是ImageView的实例化类型                    } else if (v instanceof ImageView) {                        //这里只满足数据类型为int也就是R.drawable.ic,和String类型的url,如果想实现直接用drawbale,就要实现ViewBinder                        if (data instanceof Integer) {                            setViewImage((ImageView) v, (Integer) data);                        } else {                            setViewImage((ImageView) v, text);                        }                    } else {                        throw new IllegalStateException(                                v.getClass().getName()                                        + " is not a "                                        + " view that can be bounds by this SimpleAdapter");                    }                }            }        }    }     public ViewBinder getViewBinder() {        return mViewBinder;    }     public void setViewBinder(ViewBinder viewBinder) {        mViewBinder = viewBinder;    }     public void setViewImage(ImageView v, int value) {        v.setImageResource(value);    }     public void setViewImage(ImageView v, String value) {        try {            v.setImageResource(Integer.parseInt(value));        } catch (NumberFormatException nfe) {            v.setImageURI(Uri.parse(value));        }    }     public void setViewText(TextView v, String text) {        v.setText(text);    }     public Filter getFilter() {        if (mFilter == null) {            mFilter = new SimpleFilter();        }        return mFilter;    }     public static interface ViewBinder {        boolean setViewValue(View view, Object data, String textRepresentation);    }//这个不知道干嘛用的,也没用过,好像是过滤数据的    private class SimpleFilter extends Filter {         @Override        protected FilterResults performFiltering(CharSequence prefix) {            FilterResults results = new FilterResults();             if (mUnfilteredData == null) {                mUnfilteredData = new ArrayList<Map<String, ?>>(mData);            }             if (prefix == null || prefix.length() == 0) {                ArrayList<Map<String, ?>> list = mUnfilteredData;                results.values = list;                results.count = list.size();            } else {                String prefixString = prefix.toString().toLowerCase();                 ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;                int count = unfilteredValues.size();                 ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(                        count);                 for (int i = 0; i < count; i++) {                    Map<String, ?> h = unfilteredValues.get(i);                    if (h != null) {                         int len = mTo.length;                         for (int j = 0; j < len; j++) {                            String str = (String) h.get(mFrom[j]);                             String[] words = str.split(" ");                            int wordCount = words.length;                             for (int k = 0; k < wordCount; k++) {                                String word = words[k];                                 if (word.toLowerCase().startsWith(prefixString)) {                                    newValues.add(h);                                    break;                                }                            }                        }                    }                }                 results.values = newValues;                results.count = newValues.size();            }             return results;        }         @Override        protected void publishResults(CharSequence constraint,                FilterResults results) {            // noinspection unchecked            mData = (List<Map<String, ?>>) results.values;            if (results.count > 0) {                notifyDataSetChanged();            } else {                notifyDataSetInvalidated();            }        }    }}
最近在公司涨了很多姿势,大部分是Java的继承,接口,多态,抽象这些学过但是理解很肤浅的东西,以前自己写软件没什么规范,也没怎么去抽象,所以代码很不上档次,老鸟看到我的代码就笑话我,现在我准备好好学一下,希望自己有一天也能写出很正规的代码。
--------------------- 
作者:进击的小羊 
来源:CSDN 
原文:https://blog.csdn.net/mobilexu/article/details/9850555 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值