在网上看到了关于ListView原理介绍的一个图,觉得比较不错:
下面就来说一下ListView:
listView的原理确实如图所示,当listView所显示的高度有限,其中所有的item不能够同时展现时,listview就会加载界面上能够显示的item,
当滑动listview来查看其它item时,部分显示的item就会被隐藏,被隐藏掉的item就会被回收。当查看没有显示出来的item时,如果listview存在被回收的item,就会将此回收的item返回,
问题有了,被回收的item维持着原来的数据,而我们想看到的是新的item的数据,所以需要对item上的数据组件重新赋值。
getView方法有三个参数:
position为 item在整个ListView中,包括没有展示的item,所在的位置,
convertView为listView提供的视图,
parent为该视图所在的父容器,
View getView(int position, View convertView, ViewGroup parent)
将item的布局文件转换成view的方法为:
View v=LinearLayout.inflate(this,R.layout.t_class_item,null);
convertView有可能是被回收的item视图,也有可能是未初始化的视图,因为LinearLayout.inflate方法非常消耗系统资源,而且对应用的性能 有很大的影响
所以可以判断convertView是否为null,如果不为null,那么不用再将xml布局文件inflate成View,从而太高了ListView的性能。
获取convertView后,需要对其中的数据展示组件 进行数据的赋值,比如说其中有一个TextView,获得这个textView 是通过ConvertView的findViewById(int rsID)方法来获得,
然后textView.setCharSequence("XXX");来赋值,findViewByID方法会将rsID对应到相应的View,然后把View映射到相应的子视图,此方法也是非常消耗资源,对应用性能 有非常大的影响,
所以可以将convertView自身的数据组件 缓存到自身的内存中,实现方法是,将自身的需要赋值数据的组件放到一个对象中,将该对象使用自身方法setTag放到自身的缓存中。
下面是示例代码:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView =
LinearLayout.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView)
convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ?
mIcon1 : mIcon2);
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
好吧,总之,为了尽量消除影响性能的方法 LinearLayout.inflate 和 findViewById,我们采用了如上的解决办法,经过实际的考验,此解决方法看起来还是非常不错的。