Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位、重复、闪烁分析以及解决方案,具体问题分析以及解决方案请看下文。
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位、重复、闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化。
比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而ImageView控件就是View对象通过findViewById()获得的,而我们在复用View对象时,同时这个ImageView对象也被复用了。比如第11个Item的View复用了第1个Item View对象,那么ImageView就同时被复用了,所以当图片没下载出来,这个ImageView(第11个Item)显示的数据就是复用(第1个Item)的数据。
1:Item图片显示重复
这个显示重复是指当前行Item显示了之前某行Item的图片。
比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中ListView已经滑动到了第14行,且滑动过程中该图片加载结束。第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的View对象可能被第14行复用,这样我们看到的就是第14行显示了本该属于第2行的图片,造成显示重复。
2. Item图片显示错乱
这个显示错乱是指某行Item显示了不属于该行Item的图片。
跟上面的原因一样。
3. Item图片显示闪烁
上面介绍的另外一种情况,如果第14行图片又很快加载结束,所以我们看到第14行先显示了复用的第2行的图片,立马又显示了自己的图片进行覆盖造成闪烁错乱。
解决方案:
通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getView能给对象一个标识,在异步加载完成时比较标识与当前行Item的标识是否一致,一致则显示,否则不做处理即可。
原理:首先给ImageView设置一个Tag,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position中的url对比,如果不相同就加载,相同就是复用以前的就不加载了。
Android在ListView显示图片(重复错乱闪烁问题)
1、原因分析
ListView item缓存机制:
为了使得性能更优,ListView会缓存行item(某行对应的View)。
ListView通过adapter的getView函数获得每行的item。
滑动过程中
a. 如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存;
b. 获取滑入屏幕的行item之前会先判断缓存中是否有可用的item,如果有,做为convertView参数传递给adapter的getView。
这样,如下的getView写法就可以充分利用缓存大大提升ListView的性能。即便上万个行item,最多inflate的次数为n,
n为一屏最多显示ListView 行item的个数。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
@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 ( ) ; }} |
这样提升了性能,但同时也会造成另外一些问题:
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的标识是否一致,一致则显示,否则不做处理即可。
andbase中的实现代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/** * 显示这个图片,解决了列表问题. * 列表问题:滑动过程中,getView的imageView会重复利用,导致图片会串位 * @param imageView 显得的View * @param url the url * @return */ public void display( final ImageView imageView,String url) { if (AbStrUtil.isEmpty(url)){ if (noImage != null ){ if (loadingView != null ){ loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } imageView.setImageDrawable(noImage); } return ; } //设置下载项 final AbImageDownloadItem item = new AbImageDownloadItem(); //设置显示的大小 item.width = width; item.height = height; //设置为缩放 item.type = type; item.imageUrl = url; final String cacheKey = AbImageCache .getCacheKey(item.imageUrl, item.width, item.height, item.type); item.bitmap = AbImageCache.getBitmapFromCache(cacheKey); //if(D) Log.d(TAG, "缓存中获取的"+cacheKey+":"+item.bitmap); //设置标记 imageView.setTag(url); if (item.bitmap == null ){ //先显示加载中 if (loadingView!= null ){ loadingView.setVisibility(View.VISIBLE); imageView.setVisibility(View.INVISIBLE); } else if (loadingImage != null ){ imageView.setImageDrawable(loadingImage); } //下载完成后更新界面 item.setListener( new AbImageDownloadListener() { @Override public void update(Bitmap bitmap, String imageUrl) { //未设置加载中的图片,并且设置了隐藏的View if (loadingView != null && imageUrl.equals(imageView.getTag())){ loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } //要判断这个imageView的url有变化,如果没有变化才set, //有变化就取消,解决列表的重复利用View的问题 if(bitmap!=null&& imageUrl.equals(imageView.getTag())){ if (D) Log.d(TAG, "图片下载,设置:" +imageUrl); imageView.setImageBitmap(bitmap); } else { if (errorImage != null && imageUrl.equals(imageView.getTag())){ imageView.setImageDrawable(errorImage); } } } }); if (D) Log.d(TAG, "图片下载,执行:" +url); mAbImageDownloadPool.execute(item); } else { if (loadingView != null ){ loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } imageView.setImageBitmap(item.bitmap); } } |
以上内容就是Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案,希望对大家今后的工作和学习有所帮助。
Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法的更多相关文章
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
- Android 实现ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
- Android之ListView异步加载图片且仅显示可见子项中的图片
折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...
- listview异步加载图片并防止错位
android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 conver ...
- 又优化了一下 Android ListView 异步加载图片
写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...
- wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)
wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...
- ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
- ListView异步加载图片,完美实现图文混排
昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...
随机推荐
- 【转】Linux 服务器安全配置
第一部分:RedHat Linux篇1.概述 Linux服务器版本:RedHat Linux AS 2.1 对于开放式的操作系统---Linux,系统的安全设定包括系统服务最小化.限制远程存取.隐藏重 ...
- iOS-OC、Swift 混编之桥接文件
新建一个OC语言的项目,然后添加一个基于NSObject的Swift文件SwiftFileModel类 .swift import UIKit class SwiftFileModel: NSObje ...
- 《Thinking in Java》学习笔记(一)
服务器端的编程可以参考另一本书<企业Java编程>(Thinking in Enterprise Java). 1.基本类型 基本型别 大小 最小值 最大值 默认值 boolean -- ...
- BZOJ 3209: 花神的数论题 [数位DP]
3209: 花神的数论题 题意:求\(1到n\le 10^{15}\)二进制1的个数的乘积,取模1e7+7 二进制最多50位,我们统计每种1的个数的数的个数,快速幂再乘起来就行了 裸数位DP..\(f ...
- 【IT人】如何提高阅读源代码的效率
1.最近刚到公司,公司就发一架构代码自己看,看了几天看的想吐,也在网上找了下相关的技巧吧,不是有句话叫做:成功必有方法,失败总是借口! 2.借鉴别人的方法来看看如下: 记得在开源流行之前,我看过的代码 ...
- javascript 数字字母组合的随机数
Math.random()方法用于生成,结果为0-1间的一个伪随机数(包括0,不包括1) ,通常的办法是结合parseInt().Math.floor() 或者 Math.ceil()进行四舍五入处理 ...
- 针对Eclipse的maven Missing artifact com.microsoft.sqlserver:slqjdbc4:jar:4.0
maven 中添加sqlserver 出错,报错内容 maven Missing artifact com.microsoft.sqlserver 解决方法这里先下载好jar包 ,然后maven命令执 ...
- javascript函数大全
JavaScript函数大全 1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:document->html->( ...
- APACHE服务器出现No input file specified.解决方案
thinkcmf程序默认的.htaccess里面的规则: <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_F ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...