ListView之getView详解
首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(Inflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。
然后来看函数原型public
View getView(
int
position, View convertView,
ViewGroup parent),参数中position是指当前item在屏幕中的位置,convertView相当于缓存的作用。函数返回一个View作为ListView中一个item的布局。
下面看一个getView()例子:
public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); // 获取当前项的Fruit实例 View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false); viewHolder = new ViewHolder(); viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image); viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name); view.setTag(viewHolder); // 将ViewHolder存储在View中 } else { view = convertView; viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder } viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName()); return view; }
假设一个ListView有50个item,一个屏幕最多显示ListView的10个item。当开始显示时,屏幕先显示前10个item,这10个item都是初次加载,所以convertView为空,这时候创建一个viewHolder(viewHolder起到储存和关联layout中的相关控件),然后再将viewHolder储存在要返回的View中。之后layout中的控件动态关联resource文件夹下的图片等。
每次新加载一个item时都重复上述的动作。
但当你向前滑动,浏览之前加载过的item时,convertView缓存的作用就会提高性能,此时,之前在该位置返回的View会作为getView()的convertView参数传入,所以convertView不为空,直接进行赋值操作,再取出之前储存在View中的viewHolder,无需创建新的View和viewHolder,性能大大提高。