最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决
主要分析Android ListView滚动过程中图片显示重复、错乱、闪烁的原因及解决方法,顺带提及ListView的缓存机制。
1、原因分析
ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View)。ListView通过adapter的getView函数获得每行的item。滑动过程中,
a. 如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存;
b. 获取滑入屏幕的行item之前会先判断缓存中是否有可用的item,如果有,做为convertView参数传递给adapter的getView。
更具体可见源代码ListView.obtainView。
这样,如下的getView写法就可以充分利用缓存大大提升ListView的性能。即便上万个行item,最多inflate的次数为n,n为一屏最多显示ListView 行item的个数。
a. 行item图片显示重复
这个显示重复是指当前行item显示了之前某行item的图片。
比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中listView已经滑动到了第14行,且滑动过程中该图片加载结束,第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的view可能被第14行复用,这样我们看到的就是第14行显示了本该属于第2行的图片,造成显示重复。
b. 行item图片显示错乱
这个显示错乱是指某行item显示了不属于该行item的图片。
比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中listView已经滑动到了第14行,第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的view可能被第14行复用,第14行显示了第2行的View,这时之前的图片加载结束,就会显示在第14行,造成错乱。
c. 行item图片显示闪烁
上面b的情况,第14行图片又很快加载结束,所以我们看到第14行先显示了第2行的图片,立马又显示了自己的图片进行覆盖造成闪烁错乱。
2、解决方法
通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getView能给对象一个标识,在异步加载完成时比较标识与当前行item的标识是否一致,一致则显示,否则不做处理即可。
下面以使用ImageCache为ListView提供图片获取缓存为例,ListView中强烈推荐使用ImageCache。
首先在listview adapter的getView中添加
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.list_item, null); holder = new ViewHolder(); …… convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } …… // add tag for image, to compare it when image loaded finish imageView.setTag(imageUrl); // if not in cache, restore default if (!Cache.ICON_CACHE.get(imageUrl, imageView)) { imageView.setImageDrawable(null); } }
其中setTag表示设置标识,方便下面进行标志比对
if (!Cache.ICON_CACHE.get(imageUrl, imageView))
Cache.ICON_CACHE为ImageCache的实例,表示如果不在缓存内则设置drawable为null(当然你可以可以设置为你自己的默认资源),防止显示了之前某个行item的图片,解决了a. 行item图片显示重复问题。
在ImageCache的OnImageCallbackListener的onImageLoaded函数中添加
public void onImageLoaded(String imageUrl, Drawable imageDrawable, View view, boolean isInCache) { // can be another view child, like textView and so on if (view != null && imageDrawable != null) { ImageView imageView = (ImageView)view; // add tag judge, avoid listView cache and so on String imageUrlTag = (String)imageView.getTag(); if (ObjectUtils.isEquals(imageUrlTag, imageUrl)) { imageView.setImageDrawable(imageDrawable); } } };
在上面用String imageUrlTag = (String)imageView.getTag();取得之前设置的tag,然后和当前的url进行比较,如果相等则显示,解决了b. 行item图片显示错乱,c. 行item图片显示错乱的两个问题。其中ObjectUtils可见ObjectUtils@Github.
其他异步加载过程解决原理类似。
你可能还感兴趣:
Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
Android系统下载管理DownloadManager功能介绍及使用示例
相关推荐
android中listview是比较常见的组件,通过本文主要给大家分析Android中Listview滚动过程造成的图片显示重复、错乱、闪烁的原因及解决方法,顺便跟进Listview的缓存机制,感兴趣的朋友一起看下吧
Android ListView 滑动分页 分页加载数据
网上大部分都是写的item上面显示静态图片的例子,我这个是解决显示动态图片时复用导致的动画显示错乱问题。问题描述:假如一屏可以显示10个item项,如果第一个正在播放动画,此时往下滚动,当第一个item不可见时会...
Android listview viewpager 滑动 跳动 冲突解决 ListView中嵌套ViewPage有或者滑动手势冲突解决 blog 地址 : http://blog.csdn.net/aaawqqq/article/details/43824631
解决复杂布局,scrollview嵌套ListView滑动性能的问题,提供下拉刷新和暴露对外操作listview控件UI的方法,同步博文:http://blog.csdn.net/qq_28690547/article/details/50792439
ListView每页加载10条数据,当滑动到页尾时自动加载下面的数据。
公司有个项目要用到类似手机QQ聊天记录列表ListView左右滑动后改变item的效果,网上没找到好的代码,偶然在安卓巴士的开源站http://d.apkbus.com/里面找到了SwipeToDismiss的源码...改成自己的显示另一个view的效果就行...
android listview滑动到底部加载更多数据
实现ListView选项左右滑动,可以再该demo基础上实现自己想要的效果,如滑动删除等
很多朋友在Android开发listview过程中都会碰到问题 比如从网上下载图片显示在界面 如果图片稍微大一点就会出现oom 或者显示的时候很容易出现图片闪烁等 这个项目能帮你解决
滑动listview标题置顶,listview吸顶效果,安卓系统状态栏透明,有图有源码
Android实现ListView滑动删除实现了Android中的ListView滑动删除功能,亲测可用哦
关于listview item重用导致图片重复加载 图片重新请求
android listview滑动删除
Android完美解决listview中多个edittext显示混乱问题,内含源码及apk文件
listView 滑动显示首字母 listView 滑动显示首字母
可实现listview上拉加载刷新, /** * Android下拉刷新自动加载更多 * @author mzba * */ public class PullToRefreshActivity extends ListActivity { private LinkedList, String>> mListItems; private ...
主要是实现了listview滑动删除,以及对view的滑动测试
Android ListView滑动删除