Android ListView滑动过程中控件显示重复/错误问题之原理分析...
2015-07-16 10:00
609 查看
Android ListView滑动过程中控件显示重复/错误问题之原理分析及解决方案
出处:http://www.apkbus.com/android-244461-1-1.html
前言:
为了使ListView性能更优,最普遍的方法就是添加一个ViewHolder静态类。
虽然性能有很大的提高,但是同样也伴随着Item控件内容显示重复或错乱的情况。
分析并解决如下两个问题
一、控件数据未初始化而导致的显示错误。
二、网络异步加载导致出现显示错误、重复。
如下我们来简单分析一下ListView的缓存机制。 我们整篇文章均以下图的模型来举例说明。
( 图片转至 http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html) 上图中的过程分析:
1.在getView()获取每行的Item并向下滑动的过程中,如果Item1已经完全滑出屏幕,且缓存中没有Item1对应的View,则将其put进缓存中。
2.将要滑入的Item8会先判断缓存中是否有可用的Item,如果有则直接将缓存中对应的View拿过来复用。
3.ListView显示刚刚滑入的Item8,并将ListView中的各个Item都执行刷新(getView())操作。
那么问题来了...
一、控件数据未初始化而导致的显示错误
执行Item8的getView()过程中由于复用的是Item1,那么Item8的所有初始值就是Item1的值,如果在Item8中没有对Item中任何控件重新赋值的话,那么显示的内容会和跟Item1一模一样。
实例代码:
[Java] 纯文本查看 复制代码
?
运行效果如下
我们发现Item7之后由于未重新赋值,所以都是复用的ListView缓存机制中的View。
问题的解决:
这个问题比较好解决,就是把每项Item所有控件都赋值,这样就把缓存中的初始数据给覆盖掉。
代码如下
[Java] 纯文本查看 复制代码
?
效果图:
问题解决。
二、网络异步加载导致出现显示错误、重复。
举个例子,比如Item有点赞功能,由于比较懒,未做实例,所以来来来...大家跟我一起在脑海中想象吧。
我们假设用户点了Item1的赞按钮(此时开始请求服务器...),当请求服务器的过程中,你突然向下滑动。
如上图所示,Item1被放入缓存,而Item8复用Item1的View。就在这时Item1的点赞请求刚刚请求成功,并执行显示赞状态的操作,此时Item8由于是复用的Item1的View,所以Item8的赞按钮就会被莫名其妙的点亮。然后就蒙圈了,就开始寻思,谁?谁啊?你谁?图片的加载错误也是这个原因。(图片的解决方案http://www.trinea.cn/android/android-listview-display-error-image-when-scroll/
)
3个解决方案:
1 . 不使用 ViewHolder就不存在这种问题,每次有Item滑入会重新创建控件,但这你能用吗?好吧,愿意用就用吧;
2 . HashMap来标记对应的View(HashMap<position,view>),如果item特别少你也可以用,如果Item多的话,有多少个View就会有多少个键值对,所以内存会越来越大, 也不科学;
3 . Tag标记,最终方案。
下面我们来讲解一下通过Tag标记来解决上述问题。
先贴一下纯手打的代码
[Java] 纯文本查看 复制代码
?
问题解决。
针对上面的代码,讲一下Tag在ListView中的所起的作用。
用户在Item1点了赞按钮后,此时Item1的Button进入请求服务器的过程中,用户向下滑,Item1滑出,将View复用给Item8并让其显示之后,此时Item1和Item8同时控制着同一个View,只不过Item8在显示的时候已经把复用的View重新按照它的数据覆盖了一下并把View上viewHolder.btnZ的tag重新标记成它的标记,而假设此时恰好Item1的请求才刚刚成功并要刷新了一下自己的控件,然而根据上面的代码...Item如果要显示自己的加载成功之后的状态,需要判断一下tag和position,此时Item1执行viewHolder.btnZ.getTag()方法,发现tag已经是7了(Item8的),而Item1自己的position是0。所以,被无情的拒绝在了门外~
所以我们用这种对比的方法就可以很轻松的来避免Item显示出错的问题。
总结一下:
在出现异步加载的过程中,滑动ListView,Item被复用且前一个Item刚刚异步加载成功的情况下。
getTag()获取的是当前正在显示的”正确的"Item标记,而position则很可能是复用View之前的那个Item。
如果了解上述原理,相信不管是图片还是button神马的都可以避免出现显示错误的问题啦。
出处:http://www.apkbus.com/android-244461-1-1.html
前言:
为了使ListView性能更优,最普遍的方法就是添加一个ViewHolder静态类。
虽然性能有很大的提高,但是同样也伴随着Item控件内容显示重复或错乱的情况。
分析并解决如下两个问题
一、控件数据未初始化而导致的显示错误。
二、网络异步加载导致出现显示错误、重复。
如下我们来简单分析一下ListView的缓存机制。 我们整篇文章均以下图的模型来举例说明。
( 图片转至 http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html) 上图中的过程分析:
1.在getView()获取每行的Item并向下滑动的过程中,如果Item1已经完全滑出屏幕,且缓存中没有Item1对应的View,则将其put进缓存中。
2.将要滑入的Item8会先判断缓存中是否有可用的Item,如果有则直接将缓存中对应的View拿过来复用。
3.ListView显示刚刚滑入的Item8,并将ListView中的各个Item都执行刷新(getView())操作。
那么问题来了...
一、控件数据未初始化而导致的显示错误
执行Item8的getView()过程中由于复用的是Item1,那么Item8的所有初始值就是Item1的值,如果在Item8中没有对Item中任何控件重新赋值的话,那么显示的内容会和跟Item1一模一样。
实例代码:
[Java] 纯文本查看 复制代码
?
我们发现Item7之后由于未重新赋值,所以都是复用的ListView缓存机制中的View。
问题的解决:
这个问题比较好解决,就是把每项Item所有控件都赋值,这样就把缓存中的初始数据给覆盖掉。
代码如下
[Java] 纯文本查看 复制代码
?
问题解决。
二、网络异步加载导致出现显示错误、重复。
举个例子,比如Item有点赞功能,由于比较懒,未做实例,所以来来来...大家跟我一起在脑海中想象吧。
我们假设用户点了Item1的赞按钮(此时开始请求服务器...),当请求服务器的过程中,你突然向下滑动。
如上图所示,Item1被放入缓存,而Item8复用Item1的View。就在这时Item1的点赞请求刚刚请求成功,并执行显示赞状态的操作,此时Item8由于是复用的Item1的View,所以Item8的赞按钮就会被莫名其妙的点亮。然后就蒙圈了,就开始寻思,谁?谁啊?你谁?图片的加载错误也是这个原因。(图片的解决方案http://www.trinea.cn/android/android-listview-display-error-image-when-scroll/
)
3个解决方案:
1 . 不使用 ViewHolder就不存在这种问题,每次有Item滑入会重新创建控件,但这你能用吗?好吧,愿意用就用吧;
2 . HashMap来标记对应的View(HashMap<position,view>),如果item特别少你也可以用,如果Item多的话,有多少个View就会有多少个键值对,所以内存会越来越大, 也不科学;
3 . Tag标记,最终方案。
下面我们来讲解一下通过Tag标记来解决上述问题。
先贴一下纯手打的代码
[Java] 纯文本查看 复制代码
?
针对上面的代码,讲一下Tag在ListView中的所起的作用。
用户在Item1点了赞按钮后,此时Item1的Button进入请求服务器的过程中,用户向下滑,Item1滑出,将View复用给Item8并让其显示之后,此时Item1和Item8同时控制着同一个View,只不过Item8在显示的时候已经把复用的View重新按照它的数据覆盖了一下并把View上viewHolder.btnZ的tag重新标记成它的标记,而假设此时恰好Item1的请求才刚刚成功并要刷新了一下自己的控件,然而根据上面的代码...Item如果要显示自己的加载成功之后的状态,需要判断一下tag和position,此时Item1执行viewHolder.btnZ.getTag()方法,发现tag已经是7了(Item8的),而Item1自己的position是0。所以,被无情的拒绝在了门外~
所以我们用这种对比的方法就可以很轻松的来避免Item显示出错的问题。
总结一下:
在出现异步加载的过程中,滑动ListView,Item被复用且前一个Item刚刚异步加载成功的情况下。
getTag()获取的是当前正在显示的”正确的"Item标记,而position则很可能是复用View之前的那个Item。
如果了解上述原理,相信不管是图片还是button神马的都可以避免出现显示错误的问题啦。
相关文章推荐
- 【Android】桌面歌词悬浮效果简单实现
- 如何使用 Android Studio 的 git hub 功能
- 优化Android Studio/Gradle构建
- Android多媒体高级编程(一)——Camera和简单的图像处理
- android之ScrollView里嵌套ListView
- android ndk jni 字符串 String jstring
- Android ListView滑动过程中控件显示重复/错误问题之原理分析...
- Android 自定义圆形图片和文本
- Android ant自动打包APK
- Android ListView滑动过程中图片显示重复错位闪烁问题解决
- Android Studio 设置内存大小及原理
- GitHub 优秀的 Android 开源项目
- Android HandlerThread 的使用及其Demo
- android 仿EF看视频弹出练习功能
- Android Studio
- 从设计到实现,一步步教你实现Android-Universal-ImageLoader-工具类
- Android Fragment使用
- Android中使用OnClickListener接口实现按钮点击的低级失误
- Android studio 解决libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
- Android 不规则封闭区域填充 手指秒变油漆桶