Android ListView滑动过程中图片显示重复错乱闪烁问题解决

news/2024/7/5 6:53:14

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

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

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

其中setTag表示设置标识,方便下面进行标志比对

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

 

在ImageCache的OnImageCallbackListener的onImageLoaded函数中添加

在上面用String imageUrlTag = (String)imageView.getTag();取得之前设置的tag,然后和当前的url进行比较,如果相等则显示,解决了b. 行item图片显示错乱,c. 行item图片显示错乱的两个问题。其中ObjectUtils可见ObjectUtils@Github.

其他异步加载过程解决原理类似。


http://www.niftyadmin.cn/n/3649517.html

相关文章

uTools 打造专属的办公开发效率工具

我们平时需要借助各种软件工具来完成繁杂的工作,不过零散的工具不便于管理,往往在需要时却怎么也找不到。现在有了uTools这款跨平台的桌面增强软件,这一问题迎刃而解。它提供了一-个可以随时呼之欲出的搜索框,想要使用的工具&…

speech api_如何使用Web Speech API构建文本语音转换应用

speech api介绍 (Introduction) Assuming that you’ve used several apps over the years, there is a very high chance that you have interacted with apps that provide some form of voice experience. It could be an app with text-to-speech functionality, like read…

浅谈WebView的使用

WebView是Android中一个非常实用的组件,它和Safai、Chrome一样都是基于Webkit网页渲染引擎,可以通过加载HTML数据的方式便捷地展现软件的界面。使用WebView开发软件有一下几个优点: 1.可以打开远程URL页面,也可以加载本地HTML数据…

Oracle Database 12C 安装与连接

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强&#x…

dcoker inspec_如何使用InSpec和Kitchen测试您的Ansible部署

dcoker inspecThe author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program. 作者选择了“技术多元化”基金来接受捐赠,这是Write for DOnations计划的一部分。 介绍 (Introduction) InSpec is an open-sou…

移动端开发:ionic集成toast消息提示插件

新建toast.service文件进行方法封装 1、新建文件命令 ionic g service service/toast 2、toast.service完整代码 import { Injectable } from angular/core; import {ToastController} from "ionic/angular";Injectable({providedIn: root }) export class ToastServ…

[EnterpriseLibrary]为什么拒绝ASPNET对性能数据进行访问

[EntLib]为什么拒绝ASPNET对性能数据进行访问编写者日期关键词郑昀ultrapower2005-6-27”Enterprise Library” ASP.NET PerfLib WMI浏览我们的ASP.NET站点,得到了这样的页面错误提示:拒绝对注册表项的访问。背景:在一台很干净的Windows 2000…

android的widget讲解

一、主要框架 1、AppWidgetProvider :继承自 BroadcastRecevier , 在AppWidget 应用 update、enable、disable 和 delete 时接收通知。其中,onUpdate、onReceive 是最常用到的方法,它们接收更新通知。 bindAppWidgetId(int appWi…