转-ListView的性能优化之convertView和viewHolder
ListView的性能优化之convertView和viewHolder
参考:http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html
最近碰到的面试题中经常会碰到问”ListView的优化”问题。所以就拿自己之前写的微博客户端的程序做下优化。
自己查了些资料,看了别人写的博客,得出结论,ListView优化大致从以下几个角度:
1.复用已经生成的convertView;
2.添加viewHolder类;
3.缓存数据(图片缓存);
4.分页加载。
一、复用convertView
首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。

图解:一个屏幕最多显示7个Item,如果当Item1滑出屏幕,此时Item1 的View被添加进Recycler中,相应的在下部要产生一个Item8,这时调用getView方法,convertView参数就是Item1 的View。
(1)Item固定高度
测试Demo:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView " + position + " " + convertView);
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.lv_item, null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.tv_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
|

首先程序启动,9个Item显示调用getView方法,这时的convertView都是null,因为没有任何Item被滑出屏幕缓存到Recycler中。所以打印的Log如图:
继续向上滑动屏幕,当Item1,Item2,Item3…..陆续滑出屏幕之后,他们之前的View得到重用。所以最终屏幕上就只是这10个View反复循环重用了(因为屏幕最多显示10个Item)。
然后我尝试把屏幕往回滚,重新滚到前面。
图解:屏幕从显示Item 17-Item26 滚到显示Item13-Item22。分析这个过程,当滚动一个Item时,Item26消失,Item16出现,所以Item16又将复用Item26的View,观察Log,的确如此,其他依次类推。仔细分析,有这样一个规律:无论怎么重用convertView,一个position的Item永远使用一个view。(比如此例中Item13 永远显示的是 5272fb00的View)。
(2)Item高度不固定
以上的例子是针对于每个Item的高度是固定的,所以很容易从定量中计算出每一个屏幕能够显示的最多Item数量。如果当一个Item的高度很根据不同情况的数据发生变化时,这样就无法得知最多显示的Item数量。
看一个例子,我的微博客户端程序,都知道微博有的有转载,有的有图片,所以说微博的每一个Item高度是不固定的。同样在getView中打出日志,显示如下图:
图解:因为没有固定的Item高度,无法计算一个屏幕中能够显示的最大高度,系统会会先创建一个View,第一轮是用这个View来试探能放多少个item,试探出结果可以放3个Item,所以第二轮的0-2才是真正创建的View,屏幕上显示了3个Item。当往下滚时,Item0没有完全出去,下面有来了个Item3,所以这时的Item有创建了一个View,屏幕上此时显示4个Item。之后4个Item就是做多显示的数量,再往上滚动,convertView就开始重用了,Item4和Item0的View是一个对象。
二、使用viewHolder类
我们都知道在getView方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。
测试Demo:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView " + position + " " + convertView);
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.lv_item, null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.tv_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
|
转-ListView的性能优化之convertView和viewHolder的更多相关文章
- ListView的性能优化之convertView和viewHolder
转载请注明出处 最近碰到的面试题中经常会碰到问"ListView的优化"问题.所以就拿自己之前写的微博客户端的程序做下优化. 自己查了些资料,看了别人写的博客,得出结论,ListV ...
- Android之ListView性能优化——使用ConvertView和ViewHolder
使用ConvertView和ViewHolder的优化是针对ListView的Adapter(BaseAdapter)的.这种优化的优点如下: 1)重用了ConveertView,在很大程度上减少了内 ...
- 【Android】以BaseAdapter做适配器的ListView及其性能优化
适配器的Java类 package com.app.adapter; import org.json.JSONArray; import org.json.JSONObject; import and ...
- 安卓ListView的性能优化
在安卓APP中LIstView这个控件可以说基本上是个APP就会用到,但是关于ListView除了需要了解其最基本的用法外,作为一个要做出高性能APP的程序员还需了解一些关于LIstView控件性能优 ...
- ListView的性能优化
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHol ...
- ListView之性能优化
listview加载的核心是其adapter,本文通过减少adapter中创建.处理view的次数来提高listview加载的性能,总共分四个层次: 0.最原始的加载 1.利用convertView ...
- 安卓中listview中性能优化的处理
1.在adapter中的getView方法中尽量少使用逻辑 不要在你的getView()中写过多的逻辑代码,我们能够将这些代码放在别的地方.比如: 优化前的getView(): @Override p ...
- ListView性能优化——convertView&viewHolder
ListView优化大致从以下几个角度:1.复用已经生成的convertView:2.添加viewHolder类:3.缓存数据(图片缓存):4.分页加载. 具体方案: 1.如果自定义适配器,那么在ge ...
- Android之ListView性能优化——一行代码绑定数据——万能适配器
如下图,加入现在有一个这样的需求图,你会怎么做?作为一个初学者,之前我都是直接用SimpleAdapter结合一个Item的布局来实现的,感觉这样实现起来很方便(基本上一行代码就可以实现),而且也没有 ...
随机推荐
- Android项目——短信发送器
因为应用要使用手机的短信服务,所以要在清单文件AndroidManifest.xml中添加短信服务权限: <?xml version="1.0" encoding=" ...
- vsftp虚拟用户配置
找了很久,终于找到像样一点的文章,很详细,参数方面懂英文基本能看懂,一个教程是否有用,关键在于细节.错了一点点就不能配下去了. ------------------------------------ ...
- -aborted-exception-during-the-exce
http://stackoverflow.com/questions/20988445/how-to-avoid-response-end-thread-was-being-aborted-excep ...
- sql 2000 NOLOCK 和 ROWLOCK 和 UPDLOCK
关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修改并释放锁,否则其他用户就无法修改该组数据. 有些数据库,包括SQL Se ...
- sql server 创建文件组,文件
添加文件组: --ADD FILEGROUP 增加文件组 ALTER DATABASE TestHekaton ADD FILEGROUP [Report] ALTER DATABASE TestH ...
- jQuery插件 -- 表单验证插件jquery.validate.js, jquery.metadata.js
原文地址:http://blog.csdn.net/zzq58157383/article/details/7718352 最常使用JavaScript的场合就是表单的验证,而jQuery作为一个 ...
- PDA通过SocketTcp+Json和SuperSocket通信方式
从Pda请求到服务器处理请求,并返回结果,Pda拿到结果的流程.
- jquery淡入淡出
html代码: <button id="b1" type="button">淡出</button> <button id=&quo ...
- windows系统安装MongoDB
最近一直在学习node.js,nodejs开发指南中有一个微博的web开发项目,由于该书出的比较早(2012出的),目前为止利用nodejs进行web开发各种组合技术都发生了很大的更新,例如书中选择的 ...
- C语言中的数组和指针以及字符串
数组名同时也是该数组首元素的地址,而指针提供了一种用来使用地址的符号方法,因此指针能够很有效地处理数组. 将一个整数加给指针,这个整数会和指针所指类型的字节数相乘,然后所得的结果会加到初始地址上 da ...