展会信息港展会大全

Android ListView滑动过程中图片显示重复错乱闪烁问题解决
来源:互联网   发布日期:2015-11-26 13:11:13   浏览:1774次  

导读:主要分析Android ListView滚动过程中图片显示重复、错乱、闪烁的原因及解决方法,顺带提及ListView的缓存机制。1、原因分析ListView item缓存机制:为了使得...

主要分析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的个数。

ListView

Adapter getView写法

Java

123456789101112131415161718192021222324

@Overridepublic 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();}} /** * ViewHolder ** @author trinea@trinea.cn 2013-08-01 */private static class ViewHolder {ImageView appIcon;TextViewappName;TextViewappInfo;}

这样提升了性能,但同时也会造成另外一些问题:

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中添加

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@Override

publicViewgetView(intposition,ViewconvertView,ViewGroupparent){

ViewHolderholder;

if(convertView==null){

convertView=inflater.inflate(R.layout.list_item,null);

holder=newViewHolder();

……

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表示设置标识,方便下面进行标志比对

1

if (!Cache.ICON_CACHE.get(imageUrl, imageView))

Cache.ICON_CACHE为ImageCache的实例,表示如果不在缓存内则设置drawable为null(当然你可以可以设置为你自己的默认资源),防止显示了之前某个行item的图片,解决了a. 行item图片显示重复问题。

在ImageCache的OnImageCallbackListener的onImageLoaded函数中添加

Java

1

2

3

4

5

6

7

8

9

10

11

publicvoidonImageLoaded(StringimageUrl,DrawableimageDrawable,Viewview,booleanisInCache){

//

can be another view child, like textView and so on

if(view!=null&&imageDrawable!=null){

ImageViewimageView=(ImageView)view;

//

add tag judge, avoid listView cache and so on

StringimageUrlTag=(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开发 教程

AiLab云推荐
推荐内容
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港