一、为什么需要优化?
自定义的Adapter核心方法是为getView,而在调用此方法的时候需要两个耗时操作(如下)。假如有1000行行布局,当我们向下滑动的时候,则需要调用1000行的inflate方法和4000行的findViewById方法,又假如当我们滑倒低向上滑的时候呢,可想CPU是多么繁忙,因此此优化是有必要的
1.inflate方法:获取布局对象
2.findViewById方法:获取控件对象
public View getView(int position, View arg1, ViewGroup arg2) {
//获得每行的大体外观框架,即布局对象
View view =Inflater.inflate(R.layout.item, null)
// 获得对象
ImageView logo=(ImageView) view.findViewById(R.id.iv_logo)
TextView title=(TextView) view.findViewById(R.id.title)
TextView version=(TextView) view.findViewById(R.id.version)
TextView size=(TextView) view.findViewById(R.id.size)
// 添加数据,注意需要强转
Map map=list.get(position)
logo.setImageResource((int) map.get("logo"))
title.setText((String)map.get("title"))
version.setText((String)map.get("version"))
size.setText((String)map.get("size"))
return view
}
二、怎样优化?
在getView方法中使用convertView和ViewHolder
1.inflate方法耗时:用convertView解决(系统提供View的对象)
2.findViewById方法耗时:用ViewHolder解决(自定义的ViewHolder类解决)
3.为什么convertView称为一级优化,ViewHolder为二级优化,因为ViewHolder是在convertView优化的基础上,锦上添花再次进一步优化。
4.getView()方法优化代码如下
public View getView(int position, View convertView, ViewGroup parent) {
//判断convertView是否为空,其来自getView方法的形参
if (convertView == null) {
//通过反射获得行布局对象
convertView = Inflater.inflate(R.layout.item, null)
}
// 获得控件对象对象
ImageView logo = (ImageView) convertView.findViewById(R.id.iv_logo)
TextView title = (TextView) convertView.findViewById(R.id.title)
TextView version = (TextView) convertView.findViewById(R.id.version)
TextView size = (TextView) convertView.findViewById(R.id.size)
// 添加数据,注意需要强转
Map map = list.get(position)
logo.setImageResource((int) map.get("logo"))
title.setText((String) map.get("title"))
version.setText((String) map.get("version"))
size.setText((String) map.get("size"))
return convertView
}
三、透过现象看本质,再看convertView的工作原理(Android自带)
1.举个简单例子,比如举办一次篮球比赛,一队总共10人,依次编写球服号码1~10,每次上场5人,当一队的1号主打中锋的球员累了时,只需要对应的6号中锋球员来替补他即可,让他暂时休息,如此类推,循环。
2.手机一屏所显示的ListView+1项是通过一一反射得到对象的–>滑出一屏item项没有被直接回收,而是暂存在回收器Recycle,直到到下一个item项出现时并且用来顶替之后出现的–>如此循环。
3.脑补草图,辅助理解和记忆。

四、心得总结
1、Android渲染ListView遵循以下原则;
a.不管ListView总量多少,Android只渲染当前屏的item项;
b.被渲染过的item项(即滑出的item项),它的视图对象会被保存在Recycler中;
c.新滑入屏幕的item项将从Recycle中直接获取缓存的视图,而不是再通过inflate方法反射获取。
2.结论
a.无论总量多少行,Recycle中只是缓存N+1个视图对象,即可保证整个ListView的显示(N为一屏显示的item数);
b.无论总量多少,inflate方法最多调用N+1次。
吃饭,好饿!