以下对Adapter的getView(intposition, View convertView, ViewGroup parent)方法做三种不同的测试。
直接打码:
原始方法:
// 方法一平均耗时: 6.3
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View item = inflater.inflate(R.layout.item, null);
((ImageView) item.findViewById(R.id.image))
.setImageResource((position & 1) == 1 ? R.drawable.img1
: R.drawable.img2);
((TextView) item.findViewById(R.id.tv)).setText(data[position]);
return item;
}
改进后:
// 方法二平均耗时: 0.8
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
convertView = inflater.inflate(R.layout.item, null);
}
((ImageView) convertView.findViewById(R.id.image))
.setImageResource((position & 1) == 1 ? R.drawable.img1
: R.drawable.img2);
((TextView) convertView.findViewById(R.id.tv)).setText(data[position]);
return convertView;
}
再次改进:
private ViewHolder holder;
// 方法三: 0.68
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
begin = System.currentTimeMillis();
if (convertView == null) {
convertView = inflater.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.tv = (TextView) convertView.findViewById(R.id.tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.image.setImageResource((position & 1) == 1 ? R.drawable.img1
: R.drawable.img2);
holder.tv.setText(data[position]);
end = System.currentTimeMillis();
total += end - begin;
System.out.println(total * 1.0 / position);
return convertView;
}
static class ViewHolder {
ImageView image;
TextView tv;
}
测试结果:
我用了500条记录,从开始一直滑动ListView到最下面,统计了这500次getView方法执行的平均时间,单位为毫秒:
方法一:6.3。
方法二:0.8。
方法三:0.68。
彪悍的结果不需要解释。
(不能上图,one week later 补上)
一些屁话:
1.ListView并不是一创建时就把所有的数据都加载,它本身有缓冲机制。
可见到不可见的Item会被回收,不可见到可见的Item会被创建添加。
如图所示:当向下滑动时,Item1就会被回收,Item8就会被创建。
2.item的创建添加靠的是getView方法,帮当屏幕滚动时该方法被调用得很强烈。
3.getView方法里的参数convertView在API里解释为:
The old view toreuse, if possible. Note: You should check that this view is non-null and of anappropriate type before using. If it is not possible to convert this view todisplay the correct data, this method can create a new view.
理解为View的再次使用,运用它可以减少重新使用inflater造成的资源滥用。但是如果ListView的item有多种类型的话,还得另外判断该convertView的类型。本例中只有一个类型。
4.如果有朋友在用ListView滚动时发现很卡,猛烈地建议告别方法一,尽量使用方法三。毕竟手机的反应时间并不是男人的战斗力时间越长越好。