Android——提升ListView的运行效率

非淡泊无以明志,非宁静无以致远。这篇文章主要讲述Android——提升ListView的运行效率相关的知识,希望能为你提供帮助。
    之所以说 ListView  这个控件很难用,就是因为它有很多的细节可以优化,其中运行效率就是很重要的一点。目前我们ListView  的运行效率是很低的,因为在 FruitAdapter  的getView()方法中每次都将布局重新加载了一遍,当 ListView  快速滚动的时候这就会成为性能的瓶颈。
        仔细观察,getView()方法中还有一个 convertView  参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。修改 FruitAdapter  中的代码,如下所示:

1 public class FruitAdapter extends ArrayAdapter< Fruit> { 2 3 …… 4 5 @Override 6 7 public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); 8 9 View view; 10 11 if (convertView == null) { 12 13 view = LayoutInflater.from(getContext()).inflate(resourceId, null); } else { 14 view = convertView; 15 16 } 17 18 ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); 19 20 return view; 21 22 } 23 24 }

【Android——提升ListView的运行效率】 
    可以看到,现在我们在 getView()方法中进行了判断,如果 convertView  为空,则使用 LayoutInflater 去加载布局,如果不为空则直接对  convertView 进行重用。这样就大大提高了  ListView 的运行效率,在快速滚动的时候也可以表现出更好的性能。
        不过,目前我们的这份代码还是可以继续优化的,虽然现在已经不会再重复去加载布局,但是每次在getView()方法中还是会调用View  的findViewById()方法来获取一次控件的实例。我们可以借助一个 ViewHolder  来对这部分性能进行优化,修改 FruitAdapter  中的代码,如下所示:
 
1 public class FruitAdapter extends ArrayAdapter< Fruit> { 2 3 …… 4 5 @Override 6 7 public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); 8 9 View view; 10 11 ViewHolder viewHolder; 12 13 if (convertView == null) { 14 15 view = LayoutInflater.from(getContext()).inflate(resourceId, null); viewHolder = new ViewHolder(); 16 17 viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image); 18 19 viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name); 20 21 view.setTag(viewHolder); // 将ViewHolder存储在View中 22 23 } else { 24 25 view = convertView; 26 27 viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder 28 29 } 30 31 viewHolder.fruitImage.setImageResource(fruit.getImageId()); 32 33 viewHolder.fruitName.setText(fruit.getName()); return view;

    我们新增了一个内部类 ViewHolder,用于对控件的实例进行缓存。当 convertView  为空的时候,创建一个 ViewHolder  对象,并将控件的实例都存放在 ViewHolder  里,然后调用 View的 setTag()方法,将 ViewHolder  对象存储在 View  中。当 convertView  不为空的时候则调用 View 的  getTag()方法,把  ViewHolder 重新取出。这样所有控件的实例都缓存在了  ViewHolder里,就没有必要每次都通过 findViewById()方法来获取控件实例了。
        通过这两步的优化之后,我们 ListView  的运行效率就已经非常不错了。
参考:《第一行代码android》
资源:http://download.csdn.net/detail/u011457627/8697337
 

    推荐阅读