一直没认真看过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. iOS 并发:NSOperation 与调度队列入门(1)

    一直以来,并发都被视为 iOS 开发中的「洪水猛兽」.许多开发者都将其视为危险地带,唯恐避之而不及.更有谣传认为,多线程代码应该尽力避免.笔者同意,如果你对并发的了解不够深入,就容易造成危险.但是,危 ...

  2. ORMBase对象/关系型数据库映射在MVC中的应用

    ORM这个字眼在我们操作数据库的时候,是我们使用频率最高的.它到底是个什么东西呢,我们先来看看一些对它的含义解释. 对象/关系数据库映射(object/relational mapping(ORM)) ...

  3. JDBC MySQL字段类型为datetime的数据取出(util.Date)

    使用ResultSet的getTimestamp方法获取java.util.Date型数据 java.util.Date time = rs.getTimestamp("time" ...

  4. 【 NOIP2015 DAY1 T2 信息传递】带权并查集

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  5. VC常用数据类型使用转换

    我们先定义一些常见类型变量借以说明 int i = 100; long l = 2001; float f=300.2; double d=12345.119; char username[]=&qu ...

  6. Android 圆角Button

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbEAAADrCAYAAADnsqiUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAA

  7. Android开发UI之控件-Android-PullToRefresh

    下拉刷新,使用的是Android-PullToRefresh,Github--https://github.com/chrisbanes/Android-PullToRefresh PullToRef ...

  8. [Hadoop源码解读](六)MapReduce篇之MapTask类

    MapTask类继承于Task类,它最主要的方法就是run(),用来执行这个Map任务. run()首先设置一个TaskReporter并启动,然后调用JobConf的getUseNewAPI()判断 ...

  9. TFS源代码管理

    一.服务器配置 1.创建一个Visual Studio Online账户 打开VS,选择团队资源管理器(视图菜单下),然后在团队资源管理器中选择注册Team Foundation Service,打开 ...

  10. arch Linux not found device 错误解决

    使用Archlinux LiveCD mount /dev.sda1 /mnt (有boot分区的挂boot) Running mkinitcpio -p linux Running grub-mkc ...