ListView的工作原理:
- ListView针对每个item,会调用adapter的getView()方法,要求adapter“我要显示了,给我一个视图”
- adapter通过getView()方法返回一个视图供请求的item显示
但是如果针对每个item,getView()方法都创建一个新视图的话,内存肯定吃不消。那么就需要用到缓存机制,也就是视图的重用。
优化思路:
- View的重用:view的每次创建耗时,因此在getView中判断convertView != null的时候就不创建了
- ViewHolder的运用:view的findViewById()方法也是比较耗时的,因此在可重用的convertView里面,把ViewHolder对象通过Tag的形式传进去,那么在view重用的时候就不需要再调用findViewById()方法来获取控件了
具体实现代码如下:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Log.d("debug", "getView() has been called!");
// 判断有没有convertView可以重用
ViewHolder holder = null;
if (convertView == null) {
Log.d("debug", "getView() convertView is null");
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_items, null);
holder.textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(holder);
} else {
Log.d("debug", "getView() convertView is not null");
holder = (ViewHolder) convertView.getTag();
}
// 为view上的控件设值
holder.textView.setText("test");
return convertView;
}
private static class ViewHolder {
TextView textView;
}
代码里面加了log,运行一下发现画面能放几个item,就生成几个converView缓存,当滑动的时候,就使用缓存中的converView。