Android 优化ListView
前言
这篇文章主要对优化ListView作简单的笔记,本文主要参考ListView的优化
ListView的RecycleBin机制
ListView被多次调用的方法就是适配器Adapter中的getView方法。getView方法需要返回一个View对象作为每个item的视图。简单来说,item的有多少个就会调用多少次getView方法。但并不是有多少个item就会创建多少个View,这样对于内存优化来说是很不友好的,如果View里面包含很多图片或者控件的话,估计手机都会卡死了。所以ListView里有一个RecycleBin机制,它会自动回收视图已经不可见的View对象,然后在滚动条向下滑动的时候将回收的View对象作为底部新出现的item来使用。所以getView方法的参数中有一个View convertView。具体可参考上述的链接,里面有详细的图片说明。
引入ViewHolder
- 对布局的优化
按照上述的机制我们可以对convertView作一层判断,因为列表中item的布局一般都是使用同一个布局(当然也会出现多布局的情况,但是使用ListView不是特别方便)。根据上述的方案,在getView中就会有如下的写法:
if(convertView==null){
convertView=LayoutInflater.from(mContext).inflate(R.layout.activity_main,null);
}else{
}
首先判断convertView是否为null,如果是则将布局xml与其绑定。这里就遵循一个原则:item的布局是不变的,变的只是布局里面的内容。
- 对控件的优化
上述的方法只是对convertView这一布局做了优化而已,由于getView方法频繁被调用,这就意味着如果按照上述的写法,布局中的控件就会被频繁的创建,如:
TextView textView=convertView.findViewById(R.id.text);
这样也会增加内存的压力。所以我们可以引入一个ViewHolder的概念,这个其实在RecyclerView中已经是常规性操作了。
class ViewHolder{
TextView textView;
public ViewHolder(View itemView) {
textView=itemView.findViewById(R.id.text);
}
}
在Adapter中编写一个ViewHolder的内部类,我们可以将上述的TextView写成这个类的成员变量,然后在其构造方法中利用convertView来初始化TextView,然后将这个ViewHolder对象用convertView.setTag方法保存起来。
ViewHolder holder;
if(convertView==null){
convertView=LayoutInflater.from(mContext).inflate(R.layout.activity_main,null);
holder=new ViewHolder(convertView);
convertView.setTag(holder);
}else{
holder= (ViewHolder) convertView.getTag();
}
当convertView不是null的时候我们就可以从中取出这个ViewHolder,这样就避免了控件重复创建的问题了。
其它
关于ListView的优化其实还有很多,譬如如果item中包含图片的话还需注意资源回收的问题。还有就是static关键字的问题,譬如将Context对象定义成static的话就很容易造成内存泄漏。
总结
以下是对ListView的优化作一次总结:
- Item布局,层级越少越好,使用hierarchyview工具查看优化。
- 复用convertView
- 使用ViewHolder
- item中有图片时,异步加载
- 快速滑动时,不加载图片
- item中有图片时,应对图片进行适当压缩
- 实现数据的分页加载