一直没认真看过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的继承,接口,多态,抽象这些学过但是理解很肤浅的东西,以前自己写软件没什么规范,也没怎么去抽象,所以代码很不上档次,老鸟看到我的代码就笑话我,现在我准备好好学一下,希望自己有一天也能写出很正规的代码。

												

Android SimpleAdapter源码详解的更多相关文章

  1. Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解

    Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解 今天主要理一下StreamingContext的启动过程,其中最为重要的就是Jo ...

  2. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

  4. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  5. saltstack源码详解一

    目录 初识源码流程 入口 1.grains.items 2.pillar.items 2/3: 是否可以用python脚本实现 总结pillar源码分析: @(python之路)[saltstack源 ...

  6. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  7. udhcp源码详解(五) 之DHCP包--options字段

    中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...

  8. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

  9. 源码详解系列(六) ------ 全面讲解druid的使用和源码

    简介 druid是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,druid还扩展 ...

随机推荐

  1. 自己写loader

    http://www.cnblogs.com/lynxcat/archive/2013/03/08/2950373.html http://addyosmani.com/blog/building-a ...

  2. 1319-n皇后问题

    描述 在n×n 格的棋盘上放置彼此不受攻击的n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于在n×n格的棋盘上放置n个皇后,任何2 个皇后不放在同一 ...

  3. Windows server 2008下开启telnet功能

    今天在windows server 2008 R2下使用telnet 来测试端口是否可以连接,结果发现如下错误:

  4. 安装Ubuntu服务器

    安装edX首先需要一台linux或Mac系统的电脑/服务器. 这里以常见的Ubuntu作为服务器系统. Ubuntu的官方网站为http://www.ubuntu.com,中文网站为http://ht ...

  5. [unity菜鸟] 修改发布成web后的logo

    1. 原始效果  (tip:在4.x的书中有介绍) 2. 打开.html文件原始代码如下 <script type='text/javascript' src='jquery.min.js'&g ...

  6. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-007-表单验证@Valid、Error

    一. Starting with Spring 3.0, Spring supports the Java Validation API in Spring MVC . No extra config ...

  7. prim(与边无关,适合稠密的图,o(n^2))---还是畅通工程

    题目1017:还是畅通工程 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1653 解决:838 题目描述:     某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“ ...

  8. Java 异常类层次结构

    在Java中,异常分为受检查的异常,与运行时异常. 两者都在异常类层次结构中. 下面的图展示了Java异常类的继承关系. 图1 粉红色的是受检查的异常(checked exceptions),其必须被 ...

  9. 自定义web服务器(四)

    关于HTTP协议的具体内容,前面章节已经有所讲解,相信读者已有所了解,在此不在累述,本章节讲解自定义web服务器.  一,.net提供自定义Web服务器的类 以下只是写主要的类 1.HTTPListe ...

  10. Bootstrap中的less基础

    在线编译 因为 less 的语法毕竟相对简单,所以一些在线工具可以很轻松的做到.比如 http://less.cnodejs.net http://www.ostools.net/less  一般都有 ...