Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 500|回复: 0

AndroidListview 滑动过程中图片显示重复错乱解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-9 20:17:52 | 显示全部楼层 |阅读模式

    主要分析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 .

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

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-11 21:03 , Processed in 0.060302 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表