Android Listview 滑动过程中提示图片重复错乱的原因及解决方法

主要分析Android中Listview滚动过程造成的图片显示重复、错乱、闪烁的原因及解决方法,顺便跟进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的个数。

@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滑动到第二行会异步加载某个图片,但是加载很慢,加载过程中listview已经加载到15行,且滑动过程中该图片加载结束,第二行 已经不再屏幕内,根据上面介绍的缓存原理,第二行的view可能被第14行服用,这样我们看到的就是14行显示了本该属于第二行的图片,造成重复。

b、行item图片显示错乱

这个显示错乱是指某行item显示了不属于该行item的图片。

比如listview滑动到第二行会异步加载某个图片,但是加载很慢,加载过程中listview已经滑动到14行,第二行已经不再屏幕内,根据上面介绍 的缓存原理,第二行的view可能被第14行的复用,第十四行显示了第二行的view这时之前的图片加载结束,就会显示在第14行,造成混乱。

c、行item图品显示闪烁

上面b情况,14行图片又很快加载结束,所以我们看到第14行先显示了第二行的图片,马上又显示了自己的图片进行覆盖造成的闪烁错乱。

2、解决方法

通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getview能给对象一个标识,在异步加载完成时比较标识与当前的item的标识是否是一致的,一致的则显示,否则不做处理即可。

代码中加上

@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();
}
。。。。。
imageview.setTag(imageurl);
if(!cache.icon_catch.get(imageurl,imageview){
imageview.setimageDrawable(null);
}
}

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

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

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

在ImageCache的OnImageCallbackListener的onImageLoaded函数中添加

Java

public void onImageLoaded ( String imageUrl , Drawable imageDrawable , View view , booleanisInCache ) {
// can be another view child, like textView and so on
if ( view != null && imageDrawable != null ) {
ImageView imageView = ( ImageView ) view ;
// add tag judge, avoid listView cache and so on
String imageUrlTag = ( 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 Listview 滑动过程中提示图片重复错乱的原因及解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android程序报错程序包org.apache.http不存在问题的解决方法

    Android Studio 2.1中使用 Android SDK 6.0(API 23),加载融云Demo时,报错: 解决办法: Android 6.0(api 23)已经不支持HttpClient了,在build.gradle中 加入 useLibrary 'org.apache.http.legacy'就可以了,如图: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们.

  • Android DaggerActivityComponent错误解决办法详解

    Android DaggerActivityComponent错误解决办法详解 在使用dagger2的过程中,如果修改了某个类的内容,第一次编译运行时总会报错:错误: 找不到符号 符号: 类 DaggerActivityComponent 位置: 程序包 com--的错误,然后再重新编译一次,才会正常运行,经过仔细的检查终于找到问题的根源: 错误的原因是build.gradle(Module:app)引入'com.google.dagger:dagger-compiler:2.0.2'使用的是c

  • Android 出现“Can't bind to local 8602 for debugger”错误的解决方法

    Android 出现"Can't bind to local 8602 for debugger"错误的解决方法 为了适应Android5.0的开发,把JDK升级到了1.7,然后在ADT中想调试一下程序(我连接的真机),结果报错如下: [2015-04-23 15:31:37 - ddms] Can't bind to local 8602 for debugger [2015-04-23 15:31:37 - ddmlib] 您的主机中的软件中止了一个已建立的连接 . java.io

  • Android studio报: java.lang.ExceptionInInitializerError 错误

    一.问题描述 Android studio导入一个项目报一堆错误: Process: xhs.com.xhswelcomeanim, PID: 1416 Java.lang.ExceptionInInitializerError at com.werb.gankwithzhihu.ui.fragment.ZhihuFragment.createPresenter(ZhihuFragment.java:33) at com.werb.gankwithzhihu.ui.fragment.ZhihuF

  • Android studio 出现错误Run with --stacktrace option to get the stack trace. Run with --info or --debu

     Android studio Run with --stacktrace option to get the stack trace. Run with --info or --debu 提示信息 Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. 其实是让你去查看更多的log信息.找到你项目的根目录,比如你的项目是MyApp

  • Android 出现:java.lang.NoClassDefFoundError...错误解决办法

    今天测试突然给我说我写的XX界面一点app就crash了! 纳尼,我肯定表示不服啊!怎么可能出现一点击就崩溃的情况呢,明明自己的测试了的! 然后我又用自己的测试机试了下没问题(Version:5.0.2),然后又使用crash的测试手机(Version:4.4),乖乖,居然是4.4才会出现的情况!(4.4以下没有验证哈!可能都会吧!!!) log显示: W/System.err: java.lang.NoClassDefFoundError: android/os/PersistableBund

  • 探究Android中ListView复用导致布局错乱的解决方案

    首先来说一下具体的需求是什么样的: 需求如图所示,这里面有ABCD四个选项的题目,当点击A选项,如果A是正确的答案,则变成对勾的图案,如果是错误答案,则变成错误的图案,这里当时在写的时候觉得很简单,只要是在点击的时候判断我点击的选项与正确答案是否一样,是一样就将图片换成正确的样式,如果不一样就换成错误的样式,于是我便写了下面的代码(只贴出了核心Adapter中的代码) package com.fizzer.anbangproject_dahuo_test.Adapter; import andr

  • Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法

    本文实例讲述了Android模拟器无法启动,报错:Cannot set up guest memory 'android_arm': Invalid argument的解决方法.分享给大家供大家参考,具体如下: [错误] 模拟器无法启动,报错:Cannot set up guest memory 'android_arm': Invalid argument [解决办法] 在AVD中(Android Virtual Device Manager)将模拟器的RAM调成512. 这里写图片描述 st

  • Android Data Binding 在 library module 中遇到错误及解决办法

    记一次 Data Binding 在 library module 中遇到的大坑 使用 Data Binding 也有半年多了,从最初的 setVariable,替换 findViewById,到比较高级的双向绑定,自定义 Adapter.Component,查看源码了解编译.运行流程,也算是小有成果,且没有碰到 Data Binding 本身实现上的问题. 然而,最近在一次重构组件化(见 MDCC 上冯森林的<回归初心,从容器化到组件化>)的过程中,碰到了一个比较严重的 BUG.已经提交 i

  • Android Listview 滑动过程中提示图片重复错乱的原因及解决方法

    主要分析Android中Listview滚动过程造成的图片显示重复.错乱.闪烁的原因及解决方法,顺便跟进Listview的缓存机制. 1.原因分析 Listview item 缓存机制:为了使得性能更优,Listview会缓存行item(某行对应的view).listview通过adapter的getview函数获得每行的item.滑动过程中, a.如果某行item已经划出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存: b.获取滑入屏幕的行item之前会先判断缓存中是否有可用的it

  • vue css 引入asstes中的图片无法显示的四种解决方法

    这里主要针对的是vuecli2中的一些问题. vue项目中,常常会有很多的图片资源,这样的资源存放位置,通常我们有两个选择:1. static,2. assets 关于这两者之间的区别,和如何选择这里就不多说了! 这里我们来说说assets目录下存放图片时,在vue组件的css样式中引入图片时将会遇到的一些问题! 正常情况,我们在本地开发调试的时候,无论什么样的方式引入图片都不会有问题.但是,一大包发布打线上,就会出现图片无法加载的情况! 这是因为,出于某些原因,有人修改了config目录下的i

  • vue组件中节流函数的失效的原因和解决方法

    今天使用节流函数的时候遇见了一个问题,搞了半天才找到原因,所以在这里做个总结. 节流函数 浏览器的一些事件,如:resize,scroll,mousemove等.这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用,加重浏览器的负担,导致用户体验非常糟糕.所以先贤们发明了节流函数,简单版本如下: function throttle (f, wait = 200) { let last = 0 return function (...args) { let now = Date.no

  • 直接双击启动tomcat中的startup.bat闪退原因及解决方法

    免安装的tomcat双击startup.bat后,启动窗口一闪而过,而且tomcat服务未启动. 原因是:在启动tomcat是,需要读取环境变量和配置信息,缺少了这些信息,就不能登记环境变量,导致了tomcat的闪退. 解决办法: 1.在已解压的tomcat的bin文件夹下找到startup.bat,右击->编辑.在文件头加入下面两行: SET JAVA_HOME=D:\Java\jdk1.6.0_10 (java jdk目录) SET TOMCAT_HOME=E:\tomcat-6.0.35

  • 浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法

    在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们发现程序执行完后并没有获取到我们想要的值,这时很有可能是因为你用的是ajax的异步调用async:true(默认情况),如: 复制代码 代码如下: function ManageCommentText(text) {var result = text;$.ajax({data: "get",url: "GetComments.aspx",data: "typ

  • asp.net中url字符串编码乱码的原因与解决方法

    先看实例 复制代码 代码如下: function webChart() {            var t = document.getElementById("txtReceive");            if (t.value == null || t.value == "") {                alert("请先进行查询");            }            else { alert(t.value);

  • Android 使用volley过程中遇到的问题解决办法

    Android 使用volley过程中遇到的问题解决办法 本文主要介绍使用 volley 过程中遇到的问题,错误提示: com.android.volley.NoConnectionError: java.io.InterruptedIOException",内容加载失败,问题出在重复调用 queue.start() 方法. 错误提示:com.android.volley.NoConnectionError: java.io.InterruptedIOException",然后就内容加

  • Android ListView的item中嵌套ScrollView的解决办法

    前沿:有时候,listview 的item要显示的字段比较多,考虑到显示问题,item外面不得不嵌套ScrollView来实现,于是问题来了,当listview需要做点击事件时,由于ScrollView的嵌套使用,拦截了listvew点击事件:只好重写listview来实现了. /** * * @author 作者:易皇星 * * @da2016年10月24日 时间: * * @toTODO 类描述: 解决 ListView中嵌套ScrollView,ScrollView拦截ListView的I

  • Android实现从缓存中读取图片与异步加载功能类

    本文实例讲述了Android实现从缓存中读取图片与异步加载功能类.分享给大家供大家参考,具体如下: 在新浪微博的微博列表中的图片,为了加速其显示也为了加快程序的响应,可以参考该图片异步加载类实现. public class AsyncImageLoader { //SoftReference是软引用,是为了更好的为了系统回收变量 private HashMap<String, SoftReference<Drawable>> imageCache; public AsyncImag

  • 解决android Listview的item中最外层Margin失效的问题

    1.在开发中发现这么一种现象: List中的Item是LinearLayout,这个Item的最外层,设置了margin属性.全部失效. 从图中可以看出, AbsListView的layoutparam不包含有Margin信息.包含有margin的layout是正常的几个基础布局. 解决方案: 在你的listview里面加上下面代码 android:divider="#00000000" android:dividerHeight="10dp" android:la

随机推荐