主要分析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();
}
}
 
这样提升了性能,但同时造成了一些问题。
本文原创:http://blog.sina.com.cn/s/blog_b15639e00101sgru.html
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表示设置标识,方便下面进行标志比对

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

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

在ImageCache的OnImageCallbackListener的onImageLoaded函数中添加

Java
1
2
3
4
5
6
7
8
9
10
11
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 .

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

AndroidListview 滑动过程中图片显示重复错乱解决方案的更多相关文章

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

    最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...

  2. iOS 自己主动登录,登录过程中一直显示载入页

    iOS开发中 假设client做的人性化一点肯定会考虑自己主动登录 事实上原理非常easy,就是再首次登录成功之后将username和password存入userdefault 下次登录的时候推断us ...

  3. Javascript在ajax提交过程中页面显示加载中,请等待效果,并在提交过程中限制确定按钮防止多次提交,提交完成后,解除提交限制

    加载中,请等待div: <div id="load" class="center-in-center" style="display:none; ...

  4. Silverlight中图片显示

    silverlight中显示一个图片有很多的中方法,xaml中的image控件或者自定编写程序来生成image控件. silverlight中显示的图片只能是Bitmap, JPG, PNG(64位颜 ...

  5. matlab保存图片成eps格式不全,导致latex中图片显示不全的问题

    我们经常会遇到这样的问题.用将matlab生成的图保存EPS格式后,用GSVIEW打开后,可以看到图片显示不全.遇到这种情况是,我们可以使用dvipdf——dvips的方法来生成PDF,这样生成的pd ...

  6. Bootstrap轮播(carousel)插件中图片变形的终极解决方案——使用jqthumb.js

    在顶求网的首页中我使用了BootStrap的轮播(carousel)插件来展示文章中的图片.我在程序中自动抓取文章的第一张图片作为该轮播控件中要显示的图片,由于文章的图片大小不一,而轮播插件的大小基本 ...

  7. mysql安装过程中出现的错误问题解决方案

    最近在学Django,因为与数据库相关,所以我下载并安装了MySQL,安装的过程真的是一把辛酸泪啊.安装过后,查看是否可以使用,出现了cann't connect to mysql server这个错 ...

  8. 安装CaffeOnSpark过程中遇到的问题及解决方案

    安装教程来自 http://blog.csdn.net/sadonmyown/article/details/72781393 首先,我使用的节点环境是ubuntu 16.04.1,事先 成功安装了s ...

  9. 对于HTTP过程中POST内容加密的解决方案

    0x00前言 前几天我师傅和我提及了这件事情 正常情况下 抓包过程中遇到加密情况会很迷茫 昨天把这个都弄了一下 也感谢大佬中间的指导 我一开始看到密码的类型下意识的是base64 但是去解密发现不对 ...

随机推荐

  1. word 中Sentences、Paragraph等含义和用法

    word 中有Words,Characters,Sentences.Paragraph,Sections 具体含义如下表达式             含义   返回的对象 Words(index)  ...

  2. How to change the property of a control from a flowlayoutpanel?

    Well, the easiest way would be to retain an explicit reference to the buttons you're adding. Otherwi ...

  3. C#使用SQLite出错:无法加载 DLL“SQLite.Interop.dll”,找不到指定的模块

    在SQLite官方下载了System.Data.SQLite,编写如下测试代码: 复制内容到剪贴板 程序代码 using (SQLiteConnection conn = new SQLiteConn ...

  4. STL总结之bitset

    STL的bitset是一个对位进行存储和操作的容器,可以轻松对bit位进行访问.   bitset的模板声明如下: template<size_t _Bits> class bitset; ...

  5. arm 交叉编译时 gcc 的 Options

    https://sourceware.org/binutils/docs/as/ARM-Options.html https://gcc.gnu.org/onlinedocs/gcc-4.5.3/gc ...

  6. puppet案例

    实例一.文件分发描述:通过puppet服务端可以向被管理机(客户端)上推送文件,方法是使用file类型的source属性 第一步:#vi /etc/puppet/fileserver.conf  1  ...

  7. SQL2005以上行变行简单实现

    用语法PIVOT参照:http://technet.microsoft.com/zh-cn/library/ms177410(v=sql.105).aspx

  8. javascript数组操作汇总

    javascript之数组操作 - 不悔的青春 - 博客园 1.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array( ...

  9. hdoj 2553 N皇后问题【回溯+打表】

    N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  10. 展开/收缩 ul

    了一个展开收缩的东东,留着以后万一用到 后台递归生成的函数(这里是一个反射参数展示,支持多层级展开显示,后台反射如何多层级解析的方法有时间再补上吧) /// <summary> /// 递 ...