Android在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 =newViewHolder ( ) ;
        ……
         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中的实现代码:

/**
     * 显示这个图片,攻克了列表问题.
     * 列表问题:滑动过程中,getView的imageView会反复利用。导致图片会串位
     * @param imageView 显得的View
     * @param url the url
     * @return
     */
    publicvoiddisplay(finalImageView
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;
        }
         
        //设置下载项
        finalAbImageDownloadItem item =newAbImageDownloadItem();
        //设置显示的大小
        item.width = width;
        item.height = height;
        //设置为缩放
        item.type = type;
        item.imageUrl = url;
        finalString 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);
            }elseif(loadingImage !=null){
                imageView.setImageDrawable(loadingImage);
            }
             
            //下载完毕后更新界面
            item.setListener(newAbImageDownloadListener() {
                 
                @Override
                publicvoidupdate(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);
        }
         
    }

andbase 介绍:http://blog.csdn.net/menglele1314/article/details/46422409

下载:http://download.csdn.net/detail/menglele1314/8786989

Android在ListView显示图片(重复混乱闪烁问题)的更多相关文章

  1. Android 自定义 ListView 显示网络上 JSON 格式歌曲列表

    本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...

  2. Android 关于listView 显示不全的问题

    刚刚在项目中发现一个bug,我是用ScrollView 嵌套 ListView的,但是我的数据只能显示一条,开始我还以为是数据有错误,经过排查以后发现是正确的 百度发现 android的架构好像没有考 ...

  3. android scrollview listview显示不全

    原来处理方法是重写ListView import android.content.Context; import android.util.AttributeSet; import android.v ...

  4. Android 使用ListView显示信息列表

    课程目标1.理解ListView的基础使用2.学会熟练运用两种适配器(ArrayAdapter.SimpleAdapter)3.学会熟练运用两种监听器(OnScrollListener.OnItemC ...

  5. Android TextView(同时显示图片+文字)

    见上图:需要图片和文字 在一起 之前的做法是用两个控件组成 <LinearLayout> <ImageView /> <TextView /> </Linea ...

  6. 探究Android中Listview显示错乱问题

    问题 最近在项目中遇到过一个很棘手的问题,就是ListView在滑动后就莫名其妙的显示错乱,网上查阅资料后问题很容易的就解决了,但是对于问题产生的原因仍是一知半解,所以不甘心的我定下心来,狠读源码,终 ...

  7. Android TextView中显示图片

    Android官方给我们提供的Html类下面的fromHtml方法 当你需要转换的HTML代码是带图片的,比如<IMG/>,那么你就需要使用到重载的第二个方法了,这个方法里面有个Image ...

  8. Android 利用ImageView显示图片

    Author: Maddock Date: 2015-07-21 因为做算法demo的需要,开发一点安卓的程序. 需求:获取UI中图像中某点的坐标. 参考:http://longshuai2007.b ...

  9. Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法

    Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...

随机推荐

  1. SilkTest Q&A 13

    Q121 :我想要测试 windows2003 上的 remote 应用,但是每次都得到如下的错误 我想要测试 windows2003 上的 remote 应用,但是每次都得到如下的错误: " ...

  2. Android——内存调试

    因调试某个重大问题,怀疑到了内存,专门写了个測试脚本.记录一下. 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/37928823 一 ...

  3. Microsoft Visual Studio International Pack 1.0 SR1--关于汉字转拼音

    Microsoft Visual Studio International Pack 1.0 SR1————微软的一个类库 地址:http://www.microsoft.com/zh-cn/down ...

  4. Java内部类——局部内部类

    局部内部类,即放在“{块中}”,局部内部类,不能被成员修饰符static修饰,且内部类的成员也不能是static. 内部类中访问局部变量“{块中}”,需要将局部变量声明为final. 可以直接访问外部 ...

  5. QtWebkit中如何将网页内容转为图片

    原地址:http://www.cnblogs.com/baizx/archive/2010/07/31/1789573.html 如何将webkit中的渲染结果也就是网页画面转换为图片   用抓图软件 ...

  6. 一道c++小编程题,

    题目: 编写一个小程序,从标准输入读入一系列string对象,寻找连续重复出现的单词,程序应该找出满足以下条件的单词的输入位置:该单词的后面紧跟着再次出现自己本身,跟 踪重复次数量多的单词及其重复次数 ...

  7. C++经典书目索引及资源下载

    C++经典书目索引: 严重申明 : 本博文未经原作者(jerryjiang)同意,不论什么人不得转载和抄袭 ! Essential C++ 中文版 层次:0基础 导读:<Essential C+ ...

  8. 8天玩转并行开发——第八天 用VS性能向导解剖你的程序

    原文 8天玩转并行开发——第八天 用VS性能向导解剖你的程序 最后一篇,我们来说说vs的“性能向导",通常我们调试程序的性能一般会使用Stopwatch,如果希望更加系统的了解程序,我们就需 ...

  9. 深入研究Clang(四) Clang编译器的简单分析

    作者:史宁宁(snsn1984) 首先我们确定下Clang编译器的详细内容和涵盖范围.之前在<LLVM每日谈之二十 Everything && Clang driver>中 ...

  10. Swift - 类型判断is 与 类型转换as

    在Swift中,通常使用is和as操作符来实现类型检查和转换.下面通过样例来演示使用方法,首先定义几个类. 1 2 3 4 5 6 7 8 9 10 11 //基类,人类 class Human{ } ...