Android ListView适配器中的getView()被复用详解
2015-07-10 11:23
585 查看
关于ListView中getView被重复调用的问题
在这之前,申明下,这篇属于总结一些网上的内容加自己实践证明。
用ListView显示数据时,自定义了一个适配器(extends BaseAdapter),然后重写了getView方法,现在出现一个问题,就是这个getView()方法:
被重复调用了;
比如我的_data中有两条数据,但是getView()方法 却被执行了四次甚至更多,请问这是神马情况?
这是什么样的情况,看了网上的资料以后我知道原来没有设置器listview 的布局方式不是fill-parent,而是wrap-content,会计算父控件的高度所以造成了一种反复调用情况,从而次数不确定。
更深层次的解释为:
View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。
对于ListView,当然每一个Item都会被调用measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。
而为什么会有很多组次调用呢?
问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。fill_parent会好一点,计算方法会比较简单,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能给View当饭吃,还是要计算出来具体的dip,所以measure还是会被调用,只是可能比wrap_content的少一点。至于自适应的它会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能这个measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。
所以,解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。
具体例子详介:
1、xml布局没有写成固定高度/fill_cntent/match_parent时;
执行结果:
不难看出,getView()一共执行了4轮,已经复用多轮;
2、写成固定高度/fill_cntent/match_parent时:
执行结果:
现在,getView()只执行了1轮;也是我们需要的结果;
以上对比就可以看出我们需要怎么去处理;
如果复用多次,在 适配器显示图片 或 点击事件 的时候,可能会导致position错乱,从而刷新显示的时候:(不对应)错位现象!
另外一个带提到的,也是listView这类带缓存控件显示的优点:
如果数据很多条(list.size()),超出屏幕很多(具体是多少没细究);listView的只会先执行一部分的getView()方法(应该就屏幕内的数据数次)而不会上来就执行list.size()全部数据的总次数;当你下滑时,getView()方法才会继续执行一部分......(其实就是listView缓存机制)哈哈....结合这个例子去看这个缓存机制,效果会好很多哦!
无奈的补充下,listView被嵌套的时候,如上:父listView追寻上述方法;子listView不管怎么设置,还是会复用多次....我也测试了好久没找到好方法(问大神,度娘什么的),如果有大神知道,可以分享下...
在这之前,申明下,这篇属于总结一些网上的内容加自己实践证明。
用ListView显示数据时,自定义了一个适配器(extends BaseAdapter),然后重写了getView方法,现在出现一个问题,就是这个getView()方法:
被重复调用了;
比如我的_data中有两条数据,但是getView()方法 却被执行了四次甚至更多,请问这是神马情况?
这是什么样的情况,看了网上的资料以后我知道原来没有设置器listview 的布局方式不是fill-parent,而是wrap-content,会计算父控件的高度所以造成了一种反复调用情况,从而次数不确定。
更深层次的解释为:
View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。
对于ListView,当然每一个Item都会被调用measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。
而为什么会有很多组次调用呢?
问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。fill_parent会好一点,计算方法会比较简单,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能给View当饭吃,还是要计算出来具体的dip,所以measure还是会被调用,只是可能比wrap_content的少一点。至于自适应的它会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能这个measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。
所以,解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。
具体例子详介:
1、xml布局没有写成固定高度/fill_cntent/match_parent时;
执行结果:
不难看出,getView()一共执行了4轮,已经复用多轮;
2、写成固定高度/fill_cntent/match_parent时:
执行结果:
现在,getView()只执行了1轮;也是我们需要的结果;
以上对比就可以看出我们需要怎么去处理;
如果复用多次,在 适配器显示图片 或 点击事件 的时候,可能会导致position错乱,从而刷新显示的时候:(不对应)错位现象!
另外一个带提到的,也是listView这类带缓存控件显示的优点:
如果数据很多条(list.size()),超出屏幕很多(具体是多少没细究);listView的只会先执行一部分的getView()方法(应该就屏幕内的数据数次)而不会上来就执行list.size()全部数据的总次数;当你下滑时,getView()方法才会继续执行一部分......(其实就是listView缓存机制)哈哈....结合这个例子去看这个缓存机制,效果会好很多哦!
无奈的补充下,listView被嵌套的时候,如上:父listView追寻上述方法;子listView不管怎么设置,还是会复用多次....我也测试了好久没找到好方法(问大神,度娘什么的),如果有大神知道,可以分享下...
相关文章推荐
- [转载]Activity中ConfigChanges属性的用法
- android之定时器AlarmManager
- Android java 与 javascript互访(相互调用)的方法例子
- 完美实现Android ListView中的TextView的跑马灯效果
- Web布局连载——两栏固定布局(五)
- 转载:On having layout
- Delphi7中Listview的常用功能汇总
- Delphi控件ListView的属性及使用方法详解
- android中ListView数据刷新时的同步方法
- Android提高之ListView实现自适应表格的方法
- Android中实现水平滑动(横向滑动)ListView示例
- C#实现ListView选中项向上或向下移动的方法
- C# listview添加combobox到单元格的实现代码
- ListView Adapter优化 实例
- Android用ListView显示SDCard文件列表的小例子
- Adapter实现ListView带多选框等状态的自定义控件的注意事项
- asp.net ListView 数据绑定
- Android之ScrollView嵌套ListView和GridView冲突的解决方法
- android ListView和ProgressBar(进度条控件)的使用方法
- Android中layout属性大全