Android中ListView的使用(三)----- 提升ListView运行效率

在上一篇在,我们虽然实现了ListView的显示,但是,它的运行效率是极低的由于数据较少,看不出差别,当数据量较大,或者ListView快速滚动时,FruitAdapter中的getView()每次都将布局重新加载一遍,这将会变成ListView性能的瓶颈,下面的内容将会修改优化上一篇中的代码。

在getView()方法中,有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以重用。我们的优化就是基于此的。

第一次优化

public class FruitAdapter extends ArrayAdapter<Fruit>{
    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
        super(context, textViewResourceId, objects);
        //textViewResourceId为ListView子项布局的Id
        resourceId = textViewResourceId;
    }

    //getView()方法在每个子项被滚动屏幕内的时候被调用
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);    //获取当前项的Fruit实例
        View view;
        if (convertView == null){
            //通过resourceId来加载我们自己定义的item的布局
            view = LayoutInflater.from(getContext()).inflate(resourceId, null);
        }else{
            //有缓存的布局就直接用,不再重复加载布局
            view = convertView;
        }
        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
        TextView fritName = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fritName.setText(fruit.getName());
        return view;        //返回我们自己定义的布局

    }
}

第一次优化的思路是,在加载布局是先判断一下有没有缓存的布局,如果没有就加载,如果有就直接拿来使用。

第二次优化

虽然我们上面已经实现了不重复加载布局,但我们发现每次调用getView()方法都会通过findViewById()来获取控件的实例,我们现在借助ViewHolder来对这一部分进行性能优化。

public class FruitAdapter extends ArrayAdapter<Fruit>{
    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
        super(context, textViewResourceId, objects);
        //textViewResourceId为ListView子项布局的Id
        resourceId = textViewResourceId;
    }

    //getView()方法在每个子项被滚动屏幕内的时候被调用
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);    //获取当前项的Fruit实例
        View view;
        ViewHolder viewHolder;
        if (convertView == null){
            //通过resourceId来加载我们自己定义的item的布局
            view = LayoutInflater.from(getContext()).inflate(resourceId, null);
            viewHolder = new ViewHolder();
            viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
            //将ViewHolder对象存储在View中
            view.setTag(viewHolder);
        }else{
            //有缓存的布局就直接用,不再重复加载布局
            view = convertView;
            //将存储在view中的ViewHolder取出
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        viewHolder.fruitName.setText(fruit.getName());
        return view;        //返回我们自己定义的布局
    }

    class ViewHolder{
        ImageView fruitImage;
        TextView fruitName;
    }
}

第二次的优化是定义了一个内部类ViewHolder(只有成员变量没有成员方法),然后在第一次加载布局时(即布局缓存为空时),将View中的控件通过findViewById()获取到控件的实例,并使用setTag()存储在view中,当以后需要控件实例时,再通过getTag()从view中取出转换成ViewHolder对象,直接使用其中的控件实例,从而避免了重复获取,优化了性能。

你可能感兴趣的:(优化,android,ListView,布局)