最近在折腾ListView的优化,发现网上有许多优秀的实现方法,但是分散在不同的代码中,希望通过这一系列文章做个总结,并梳理清楚脉络。
1、大量耗费时间的操作
调用inflate()方法可以从XML文件创建视图对象(如ListView),而这样创建对象是需要大量时间、空间开销的。
而调用findViewById()方法虽然没有inflate花费那么大,但也属于相对耗时的操作。
下面将讨论如何减少这两种操作使得ListView的性能得到优化。
2、ConvertView
ListView存储了比所展示行数更多的数据,当用户滚动列表时,某下行和他们对应的View对象将会被滚出可见区域(如下图所示),这些对象可以在新的
可见行中被重用。
如果系统判定代表一行的一个视图对象View不再可见时,可以通过getView()方法中的convertView对象重用它。
这样优化过之后的Adapter(getView()方法在Adapter中实现),可以大大减少后期的inflate()方法调用和创建新的View对象。
为了应对前期没有可重用的View的情况,可以通过判断convertView是否为null来决定是否需要调用infalte();

3、Holder模式
ViewHolder模式可以避免减少findViewById()方法的调用,核心也是重用。
ViewHolder是一个静态内部类,存储了相关视图类的引用,这个引用通过setTag()方法设置标记来指定它对应的视图(ListView布局里的一行)。
如果我们接收到一个convertView对象,可以通过getTag()方法得到ViewHolder实例,然后通过该实例设置视图对象的属性。
这样实现起来比较复杂,但相对每次调用findViewById()方法,能够提高大约15%的速度。
4、标准Adapter的性能优化
默认的Android Adapter像ArrayAdapter已经实现了性能优化,不需要自己修改实现。
5、实例
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MyPerformanceArrayAdapter extends ArrayAdapter<String> {
private final Activity context;
private final String[] names;
static class ViewHolder {
public TextView text;
public ImageView image;
}
public MyPerformanceArrayAdapter(Activity context, String[] names) {
super(context, R.layout.rowlayout, names);
this.context = context;
this.names = names;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
viewHolder.image = (ImageView) rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
if (s.startsWith("Windows7") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
holder.image.setImageResource(R.drawable.no);
} else {
holder.image.setImageResource(R.drawable.ok);
}
return rowView;
}
}