最新内容建议直接访问原文:Android ListView滑动过程当中图片显示重复错乱闪烁问题解决java
主要分析Android ListView滚动过程当中图片显示重复、错乱、闪烁的缘由及解决方法,顺带说起ListView的缓存机制。
一、缘由分析
ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View)。ListView经过adapter的getView函数得到每行的item。滑动过程当中,android
a. 若是某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,不然更新缓存;
b. 获取滑入屏幕的行item以前会先判断缓存中是否有可用的item,若是有,作为convertView参数传递给adapter的getView。
更具体可见源代码ListView.obtainView。git
这样,以下的getView写法就能够充分利用缓存大大提高ListView的性能。即使上万个行item,最多inflate的次数为n,n为一屏最多显示ListView 行item的个数。github
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行的图片,立马又显示了本身的图片进行覆盖形成闪烁错乱。app
二、解决方法
经过上面的分析咱们知道了出现错乱的缘由是异步加载及对象被复用形成的,若是每次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表示设置标识,方便下面进行标志比对ide
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.
其余异步加载过程解决原理相似。
你可能还感兴趣: