Android listView异步下载和convertView复用产生的错位问题
1:Item图片显示重复
这个显示重复是指当前行Item显示了之前某行Item的图片。
比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中ListView已经滑动到了第14行,且滑动过程中该图片加载结束。第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的View对象可能被第14行复用,这样我们看到的就是第14行显示了本该属于第2行的图片,造成显示重复。
3. Item图片显示闪烁
上面介绍的另外一种情况,如果第14行图片又很快加载结束,所以我们看到第14行先显示了复用的第2行的图片,立马又显示了自己的图片进行覆盖造成闪烁错乱。
解决方案:
通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getView能给对象一个标识,在异步加载完成时比较标识与当前行Item的标识是否一致,一致则显示,否则不做处理即可。
原理:首先给ImageView设置一个Tag,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position中的url对比,如果不相同就加载,相同就是复用以前的就不加载了。
滑动过程中
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
|
@Overridepublicint ViewHolder ifnull convertViewnull holdernew …… convertView }else holder }} |
这样提升了性能,但同时也会造成另外一些问题:
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
|
/** * * * * * */ public final if ifnull ifnull loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } imageView.setImageDrawable(noImage); } return } //设置下载项 finalnew //设置显示的大小 item.width item.height //设置为缩放 item.type item.imageUrl final .getCacheKey(item.imageUrl, item.bitmap //if(D) //设置标记 imageView.setTag(url); ifnull //先显示加载中 ifnull loadingView.setVisibility(View.VISIBLE); imageView.setVisibility(View.INVISIBLE); }else null imageView.setImageDrawable(loadingImage); } //下载完成后更新界面 item.setListener(new @Override public //未设置加载中的图片,并且设置了隐藏的View ifnull loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } //要判断这个imageView的url有变化,如果没有变化才set, //有变化就取消,解决列表的重复利用View的问题 if(bitmap!=null&& if"图片下载,设置:" imageView.setImageBitmap(bitmap); }else ifnull imageView.setImageDrawable(errorImage); } } } }); if"图片下载,执行:" mAbImageDownloadPool.execute(item); }else ifnull loadingView.setVisibility(View.INVISIBLE); imageView.setVisibility(View.VISIBLE); } imageView.setImageBitmap(item.bitmap); } } |
Android listView异步下载和convertView复用产生的错位问题的更多相关文章
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...
- Android ListView异步载入图片乱序问题,原因分析及解决方式
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android全部系统自带的控件其中,ListView这个控件算是 ...
- 又优化了一下 Android ListView 异步加载图片
写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...
- android AsyncTask异步下载并更新进度条
AsyncTask异步下载并更新进度条 //如果不是很明白请看上篇文章的异步下载 AsyncTask<String, Integer, String> 第一个参数:String 传入 ...
- android ListView异步加载图片(双缓存)
首先声明,参考博客地址:http://www.iteye.com/topic/685986 对于ListView,相信很多人都很熟悉,因为确实太常见了,所以,做的用户体验更好,就成了我们的追求... ...
- Android Listview异步动态加载网络图片
1.定义类MapListImageAndText管理ListViewItem中控件的内容 package com.google.zxing.client.android.AsyncLoadImage; ...
- 转:Android ListView 异步加载图片
http://www.iteye.com/topic/1118828 http://www.iteye.com/topic/1127914 这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的 ...
- Android ListView异步加载数据
1.主Activity public class MainActivity extends Activity { private ListView listView; private ArrayLis ...
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...
随机推荐
- linux:cpu 每-CPU 的变量
每-CPU 的变量 每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU变量, 系统中每个处理器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. ...
- python 反人类函数式编程模拟while和if控制流
比如下面这个简单明了的命令式程序,它不断捕捉用户输入的内容,然后对其求和.直到用户输入一个以'0'开头的字符串,停止捕捉. while 1: line = input() ': print(sum(m ...
- C#删除WebBrowser控件的Session
因最近做一个成绩查询导出的程序,用到webbrowser控件,该查询的网站限制一个会话只能查询3次成绩,而我要查询4000多人的成绩. using System.Runtime.InteropServ ...
- JAVA面向对象-----java面向对象的六大原则
现在编程的主流语言基本上都是面向对象的.如C#,C++,JAVA.我们在使用时,已经构造了一个个的类.但是往往由于我们在类内部或外部的设计上存在种 种问题,导致尽管是面向对象的语言,却是面向过程的逻辑 ...
- Android开源框架ViewPagerIndicator的基本使用
转载本博客请注明出处:点击打开链接 http://blog.csdn.net/qq_32059827/article/details/52495647 很多新闻资讯类的app都有一些共性,那就是 ...
- 两种配置大数据环境的方法Ambari以及hadoop源代码安装的步骤
1.Ambari安装 Ambari & HDP(Hortonworks Data Platform) ********************************************* ...
- Libgdx教程目录
Libgdx教程 Note:本教程用的Libgdx 1.9.2版本,在教程更新完毕之前应该不会更新版本.之前的博客中也发表过Libgdx的内容,不过当时都从别人那里拷贝的,因此现在想做一个Libgdx ...
- Eclipse中如何快速查看jar包中 的class源码
我们查看jar源码时,一般是安装个jd-gui,把jar拷出来,然后从jd-gui中打开jar再查看源码,这个过程不免有些麻烦,当然,本篇所讲的快速查看的方法也没什么高科技手段,只是将jd-gui集成 ...
- (一一〇)正则表达式的基本使用与RegexKitLite的使用
正则表达式常常用于匹配关键字,下面先介绍基本语法. [基本语法] ①中括号表示满足其中之一即可,例如[abc],则这个位置可以是a.b.c中任意一个. ②在中括号中,可以通过-连接范围,例如a-z:多 ...
- UNIX网络编程——客户/服务器程序设计示范(三)
TCP预先派生子进程服务器程序,accept无上锁保护 我们的第一个"增强"型服务器程序使用称为预先派生子进程的技术.使用该技术的服务器不像传统意义的并发服务器那样为每个客户现场派 ...