• android:提升 ListView 的运行效率


    之所以说 ListView 这个控件很难用,就是因为它有很多的细节可以优化,其中运行效率 就是很重要的一点。目前我们 ListView 的运行效率是很低的,因为在 FruitAdapter 的 getView() 方法中每次都将布局重新加载了一遍,当 ListView 快速滚动的时候这就会成为性能的瓶颈。

    仔细观察,getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的 布局进行缓存,以便之后可以进行重用。修改 FruitAdapter 中的代码,如下所示:

    public class FruitAdapter extends ArrayAdapter<Fruit> {

    ……

    @Override

    public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position);

    View view;

    if (convertView == null) {

    view = LayoutInflater.from(getContext()).inflate(resourceId, null);

    } else {

    view = convertView;

    }

    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());

    return view;

    }

    }

    可以看到,现在我们在 getView()方法中进行了判断,如果 convertView 为空,则使用 LayoutInflater 去加载布局,如果不为空则直接对 convertView 进行重用。这样就大大提高了 ListView 的运行效率,在快速滚动的时候也可以表现出更好的性能。

    不过,目前我们的这份代码还是可以继续优化的,虽然现在已经不会再重复去加载布局, 但是每次在 getView()方法中还是会调用 View 的 findViewById()方法来获取一次控件的实例。 我们可以借助一个 ViewHolder 来对这部分性能进行优化,修改 FruitAdapter 中的代码,如下 所示:

    public class FruitAdapter extends ArrayAdapter<Fruit> {

    ……

    @Override

    public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position);

    View view;

    ViewHolder viewHolder;

    if (convertView == null) {

    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);

    view.setTag(viewHolder); // ViewHolder存储在View

    } else {

    view = convertView;

    viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder

    } viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName());

    return view;

    }

    class ViewHolder { ImageView fruitImage; TextView fruitName;

    }

    }

    我们新增了一个内部类 ViewHolder,用于对控件的实例进行缓存。当 convertView 为空 的时候,创建一个 ViewHolder 对象,并将控件的实例都存放在 ViewHolder 里,然后调用 View 的 setTag()方法,将 ViewHolder 对象存储在 View 中。当 convertView 不为空的时候则调用 View 的 getTag()方法,把 ViewHolder 重新取出。这样所有控件的实例都缓存在了 ViewHolder 里,就没有必要每次都通过 findViewById()方法来获取控件实例了。

    通过这两步的优化之后,我们 ListView 的运行效率就已经非常不错了。

    3.5.4    ListView 的点击事件

    话说回来,ListView 的滚动毕竟只是满足了我们视觉上的效果,可是如果 ListView 中的 子项不能点击的话,这个控件就没有什么实际的用途了。因此,本小节中我们就来学习一下 ListView 如何才能响应用户的点击事件。

    修改 MainActivity 中的代码,如下所示:

    public class MainActivity extends Activity {

    private List<Fruit> fruitList = new ArrayList<Fruit>();

    @Override

    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();

    FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList);

    ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() {

    @Override

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    Fruit fruit = fruitList.get(position); Toast.makeText(MainActivity.this, fruit.getName(),

    Toast.LENGTH_SHORT).show();

    }

    });

    }

    ……

    }

    可以看到,我们使用了 setOnItemClickListener()方法来为 ListView 注册了一个监听器, 当用户点击了 ListView 中的任何一个子项时就会回调 onItemClick()方法,在这个方法中可以 通过 position 参数判断出用户点击的是哪一个子项,然后获取到相应的水果,并通过 Toast 将水果的名字显示出来。

    重新运行程序,并点击一下西瓜,效果如图 3.31 所示。

     

    图   3.31

  • 相关阅读:
    包管理器Bower使用手冊之中的一个
    开机就提示“请安装TCP/IP协议,error=10106”的解决的方法
    Apache Thrift的简单使用
    Python机器学习实战&lt;一&gt;:环境的配置
    数据库期末考试复习题 第二�
    数据集成之主数据管理(一)基础概念篇
    Cocos2d-x开发中C++内存管理
    html中#include file的使用方法
    网页的背景图片代码
    TEST
  • 原文地址:https://www.cnblogs.com/zgqys1980/p/5114273.html
Copyright © 2020-2023  润新知