首页 > 其他分享 >Android listView异步下载和convertView复用产生的错位问题

Android listView异步下载和convertView复用产生的错位问题

时间:2022-12-16 20:04:24浏览次数:51  
标签:14 图片 item convertView View imageView Android listView 加载

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

​​@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 ( ) ;​​


​​}​​


​​}​​


这样提升了性能,但同时也会造成另外一些问题:
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);​​


​​}​​


​​}​​

标签:14,图片,item,convertView,View,imageView,Android,listView,加载
From: https://blog.51cto.com/u_13657808/5948296

相关文章

  • android自定义listview实现header悬浮框效果
    之前在使用iOS时,看到过一种分组的View,每一组都有一个Header,在上下滑动的时候,会有一个悬浮的Header,这种体验觉得很不错,请看下图:上图中标红的1,2,3,4四张图中,当向上滑动时,仔细......
  • 高仿京东Android App,集成React-Native热更
    简介本项目是一个学习类型的项目,主要是为了学习一些Android最新的思路和开发思想,工程按照模块化、组件化的开发思路进行开发,项目整体结构如下图。项目代码整洁规范,结构清晰,......
  • android 制作9.png图片
    一、什么是9.png:       可能做过任务栏美化的同学都会知道,我靠,framework-res.apk\res\drawable-hdpi目录下有非常非常多的XXXXXX.9.png图片。千万不要以为这个9只......
  • android studio real phone
    https://www.csdn.net/tags/NtDakgysNTE2MTAtYmxvZwO0O0OO0O0O.htmladbdevicesnvaaeqbumnsgfenrunauthorizedadbtcpip[端口号(未被占用)],如adbtcpip5683 ......
  • Android runInstallCreate from pm command asks to run as user -1 but is calling f
    android使用pm静默安装pminstall-i“包名”-rapkPath提示错误:Android runInstallCreatefrompmcommandaskstorunasuser-1butiscallingfromuser0随......
  • Android Studio工程目录介绍,Ubuntu/Debian 系统切换Java(JVM),修改Java版本,JAVA_HOME
    AndroidStudio工程目录介绍 du1@dePc:~/asProjs/sms$./gradlewcleanERROR:JAVA_HOMEissettoaninvaliddirectory:/home/du1/aset/as/sdkPleasesettheJAVA......
  • Android系列之Volley框架加载网络图片
    Android开发中,加载网络服务器的图片是很常用的,当然我们可以自己写服务器接口去实现,不过要做到服务器性能优越的话,开发起来比较麻烦点,所以本博客要介绍Volley框架进行网络......
  • android listivew 下拉回弹刷新
    该效果是一名国外工程师(johannilsson)的代码,拿来研究了下,自己整合了一下,现在拿出来,跟大家一起分享。再次感谢这位国外工程师(johannilsson),谢谢!新浪微博,和QQ空间里面,都有那......
  • ubuntu 11.10(32位系统)下编译android源码 make错误解决办法
    本文介绍在ubuntu11.10系统下编译android2.3.3源码,编译之前请确定上两篇文章中所需的准备工作已经成功完成。编译完成生成系统镜像文件,并在模拟器中运行。准备工作完成......
  • android NTP服务器设置
    更改Android设备NTP服务器adbshellsetproppersist.sys.timezoneAsia/Shanghaiadbshellsettingsputglobalntp_serverntp.aliyun.comadbshellsettingsget......