1.1listView优化之convertView

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本篇是通用版的listView的优化,最终会使用模板设计模式和钩子方法对通用优化,在进行代码层级的深度优化。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

本篇对ConvertView优化的理解,主要基于测试和验证, 而非源码分析

通用版listView的adapter的使用,核心代码如下:


/////////////////////////////getView优化//////////////////////////////////
//基本优化:
//①使用convertView重用,避免每次getView方法的时候,都去创建新的View
//②使用ViewHolder来临时存储item中的控件,避免出现重复多次的findViewById,此操
//作也是消耗内存的操作
//③ListView的在布局中,不要设置自适应(wrap_content),这样会导致getView方法的重
//调用
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder = null;
if (convertView == null) {
        viewHolder = new ViewHolder();
        convertView = mInflater.inflate(R.layout.lv_books_items, parent, false);
        viewHolder.tv_desc = (TextView) convertView.findViewById(R.id.tv_desc);
        viewHolder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
        viewHolder.tv_price = (TextView) convertView.findViewById(R.id.tv_price);
//setTag方法学习
stu4ViewPsetTag();
        convertView.setTag(viewHolder);

    }else{
        viewHolder=(ViewHolder)convertView.getTag();
    }
    Log.e("convertView","当前的position:"+position+"当前的对象:"+convertView.toString());
return convertView;
}

test1:
第一次运行
手机屏幕上显示的item条数:
1.1listView优化之convertView_第1张图片
打印出的convertView的log信息:


结论是:

屏幕上显示了7个view,log中,每次getView方法中的convertView都是null,于是convertView每次都赋值,并返回。显然作为getView的参数的convertView是否为null和回调该方法时,传入的参数有关和此次convertView有没有赋值是没有关系的。实际上就是要理解convertView做为参数,是局部变量。
显然,在此一次显示,没有任何滑动的情况下,getView中的参数被传入的都是null。也就是说ConvertView此时还没有起到缓存的作用。接着看test2.

test2:
滑动listView到第八个item显示,第一个item没有完全隐藏。(不同的大小的手机上,一屏显示的item个数不同,可以自己调整,以操作test2)


第八次调用(position=7)getview的时候,convertView==null,有重新创建了一个对象赋值给了convertView,根据convetView.toString()方法打印结果,发现convertView仍然没有被重复使用。
原因:虽然出现了第八个item,但是convertView仍然是空的原因。是此时第一个item还没有完全隐藏。下面的test3就可以验证这个问题。

第九次调用( position=8)getView的时候,convertView!=null了,而是直接复用了第一个已经被隐藏的convertView。
继续看

test3:
继续滑动到position=15的位置。
1.1listView优化之convertView_第2张图片
结论:从结果可以看出,第一次未被复用的listView的8个局部变量convertView,在滑动的过程中全部被复用了。继续滑动的过程中也是遵守先前的顺序进行复用。

继续看test4:
test4:将listview滑动底部,在向上滑动

结论:
使用covertView对应顺序还是一致的。


那么通常给listView设置的adpater的getview中,convertView作为缓存View的逻辑就很清楚了。
总结如下

①从listview中的item第一次显示开始到顶部的第一个item完全不可见以后,第一个item通过getview返回的view才会第一次保存在起来(具体如何保存,得研究源码,比如已全局的list列表保存,然后取的时候,再从列表中取对应的)。
②只有当前面有getview被保存过后,滑动显示新的item的时候,listView回调getView方法,才会传入对应convertView,否则传的null,已起到缓存作用。
③继续滑动的过程中,都会重复使用convertView,并按照第一个使用convertView的item之前的所有item的被缓存过的view顺序进行使用。
通过以上三点,最终提高了listView的去重复创建过多item的view的过程,对堆内存有一定的优化,提高了listView的性能。




你可能感兴趣的:(viewholder,listview优化,convertView)