在上节的基础上对ListView进行优化,为什么要对ListView进行优化呢?下面来进行详解。
ListView中是通过getView去将数据显示到视图中,在每次调用getView的时候都要执行2个耗时操作。
(1)通过反射去获取行布局对象。
(2)获取控件对象
既然我们已经知道什么原因导致的了,那么问题来了,怎么去解决呢?
1.解决反射耗时问题。使用convertView进行1级优化。
(1)无论总量多少,android只渲染当前屏的item项。
(2)被渲染过的item项,它的视图对象会被保存到Recycle中。
(3)新滑入屏幕的item项将从Recycle中直接获取在回收池中缓存的视图,而不是再通过inflate方法反射获取。
总结 : 无论总量多少,Recycle中只需要缓存一屏可显示的item数个视图加1个对象,即可保证整个listview的显示。无论总量多少,inflate方法做多调用item+1次 。
2.解决获取控件耗时问题。使用ViewHolder解决。
(1)ViewHolder是一个自定义的类,它存储了通过findViewById获取来的控件对象。
(2)当ConvertView被创建时,ViewHolder也随之一起被缓存到Recycle中。
(3)当ConvertView被重新利用时,ViewHolder也随之被取出,从而可以直接给各个控件赋值,而无需再次调用findViewById方法。
总结 : 无论总量是多少,findViewById方法最多调用一屏可显示的item数个视图加1。
ConvertView和ViewHolder都是通过减少反射操作的次数来达到优化的目的。
多的不说,直接上代码。。。。
public View getView(int position, View convertView, ViewGroup arg2) {
ViewHodler hodler=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.item, null);
hodler=new ViewHodler();
hodler.logo=(ImageView) convertView.findViewById(R.id.logo);
hodler.title=(TextView) convertView.findViewById(R.id.title);
hodler.version=(TextView) convertView.findViewById(R.id.version);
hodler.size=(TextView) convertView.findViewById(R.id.size);
convertView.setTag(hodler);
}else{
hodler=(ViewHodler) convertView.getTag();
}
Map map=list.get(position);
hodler.logo.setImageResource((Integer) map.get("logo"));
hodler.title.setText((String) map.get("title"));
hodler.version.setText((String) map.get("version"));
hodler.size.setText((String) map.get("size"));
return convertView;
}
public class ViewHodler{
ImageView logo;
TextView title;
TextView version;
TextView size;
}