第十五个项目——使用ViewHolder提升ListView显示性能
实验目的
掌握ListView中Item布局加载机制;
掌握View.setTag()及View.getTag()读取数据的方式;
实验要求
自定义ViewHolder保存Item布局控件实例
修改NewsAdapter.getView()方法提升Item加载效率;
实验内容
在第七个项目中,使用了ListView用于显示新闻列表。为了实现ListView中的Item加载自定义布局,项目中实现了名为NewsAdapter的适配器类,在该类中覆盖了getView()方法。当用户上下滑动ListView时,该方法被调用; 该方法中需要返回当前postion对应的Item布局,原代码中在getView()方法中每次都通过LayoutInflater加载list_item.xml布局资源,并实例化相应的TextView、ImageView控件。
假设ListView中的数据源包含成千上万条数据,最极端的情况下,用户滑动ListView到底部,那么App将有上万个TextView、ImageView控件的实例,但是ListView能在屏幕上显示的数据远远小于数据源所包含的数据量,这样的做法无疑会降低App的运行效率。有什么办法可以提升ListView加载显示数据的效率?如果当ListView中某一Item滑出屏幕时,新滑入的Item能复用其实例化的布局就可以避免刚才所说的问题。
实际上ListView控件提供了缓存机制,可有效提高Item布局加载效率低下的问题。getView()方法的第二个参数(View convertView)如果不为null则保存了被缓存的Item布局实例。
步骤一,打开第七个项目
打开第七个项目,并打开文件NewsAdapter.java。
步骤二,定义ViewHolder类
在NewsAdapter中定义名为ViewHolder的内部类(inner class),ViewHolder中包含了list_item.xml布局中三个控件的定义,其主要作用为保存每一个Item布局中控件的实例。
步骤三,更改NewsAdapter.getView()方法
在NewsApdater适配器类的getView()方法中,通过判断convertView是否为空,可判断ListView是否缓存了Item的布局,如果已缓存则可直接使用,否则需要通过Layoutinflater进行加载。
通过LayoutInflater进行加载的Item布局中的控件实例,通过实例化ViewHolder类对象进行存储, 而通过view.setTag(Object viewHolder)将ViewHolder类对象存储于view对象中,ViewHolder对象可通过view.getTag()的方式进行读取即可。具体代码如下所示。
View.setTag(Object obj)方法的参数为Object类型,通过该方法可以把任意类型的数据跟当前的View对象进行绑定,后续还可以见到更多这类使用方式。
例如删除ListView控件中某一个Item时,首先将当前Item对应数据的Id与表示删除图标的ImageView控件进行绑定(通过setTag()方法),再实现该ImageView控件的OnClickListener事件处理器中通过getTag()方法取出Id,并执行相应的删除操作。 具体详见第十七个项目。
步骤四,编译并运行项目
编译并运行项目,其执行效果与第七个项目相同,你可以为ListView的数据源添加更多的数据对比一下其性能是否有提升。
实验小结
通过本次实验,你应该掌握了如下知识内容:
了解如何提升ListView控件运行性能;
使用ViewHolder存储ListView的Item布局控件;
使用View.setTag()、View.setTag()将数据绑定至控件;
Last updated
Was this helpful?