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 =new
ViewHolder ( ) ;

        ……

         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

     */

    publicvoid
display(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

                publicvoid
update(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

时间: 2024-10-07 21:09:37

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

Android 自定义 ListView 显示网络歌曲列表

本文内容 环境 项目结构 演示自定义 ListView 显示网络歌曲列表 参考资料 本文最开始看的一个国人的文章,没有源代码,根据文中提供的源代码,自己新建的项目(最可气的是,没有图标图片资源,只能自己乱编),但程序不是很稳定,有时能显示出列表中的缩略图,有时显示不出来,还在主线程访问了网络.后看文章评论,作者给出英文原文链接,本来想这下没事了吧,结果下载源代码运行后,还是有问题~仔细看英文原文,原来他也是根据 Github 上一个项目的基础上搞的,只是添加了式样,以及显示完整的歌曲列表,包括歌

android中如何显示图片的一部分

android中如何显示图片的一部分 分类: Android应用开发系列教程 Android应用开发技巧 2012-04-25 23:42 1728人阅读 评论(0) 收藏 举报 androidmatrixfloatconstructorclassnull 作者:张宗硕 在android应用程序中加载一张图片,然后把它显示出来这是一件非常容易的事情,那怎么才能显示一张图片的一小部分呢,一种做法是把图片ps一下,要显示的那部分单独存成一张图片,然后程序中加载它,并把它显示出来.但这样会增加程序的图

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

转自:http://www.oschina.net/question/221817_121051 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及ListView的缓存机制.1.原因分析ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View).ListView通过adapter的getView函数获得每行的item.滑动过程中, a. 如果某行item已经滑出屏幕,若该item不在缓存内,则p

Android实现ListView显示信息,点击每个item,跳转到相应界面

界面如下:(做这个目的仅仅是为了学习一点小知识,因为自己才刚开始) 实现的方法比较简单,就是定义一个ListView,然后设置监听,ListView对每个条目的监听是setOnItemClickListener. onItemClick(AdapterView<?> parent, View view, int position, long id) 这段代码中, parent           发生点击动作的AdapterView. view              在AdapterVie

android scrollview listview显示不全

原来处理方法是重写ListView import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ListView; public class MyListView extends ListView { public MyListView(Context context) { super(context); // TO

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

见上图:需要图片和文字 在一起 之前的做法是用两个控件组成 <LinearLayout> <ImageView /> <TextView /> </LinearLayout> 今天读人家的源码,发现原来一个TextView就可以实现: <TextView android:id="@+id/btn_middle" style="@style/style_topbar_textview_shadow" android

Android 利用ImageView显示图片

Author: Maddock Date: 2015-07-21 因为做算法demo的需要,开发一点安卓的程序. 需求:获取UI中图像中某点的坐标. 参考:http://longshuai2007.blog.163.com/blog/static/1420944142011611105732712/ http://www.eoeandroid.com/forum.php?mod=viewthread&tid=177689&extra=page%3D1&ordertype=1 htt

pyqt listview显示图片

def findImage(self,ext='jpg|png|bmp|gif'):    import os    image=self.OpenEdit.text()    allfiles = []    needExtFilter = (ext != None)    for root,dirs,files in os.walk(unicode(image)):        for filespath in files:            filepath = os.path.jo

Android 自定义 ListView 上下拉动&ldquo;刷新最新&rdquo;和&ldquo;加载更多&rdquo;歌曲列表

本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码太多,点击此处下载,自己调试一下. 下载 Demo 环境 Windows 2008 R2 64 位 Eclipse ADT V22.6.2,Android 4.4.3 SAMSUNG GT-I9008L,Android OS 2.2.2 测试数据 本演示的歌曲信息,共有 20 条,包括歌手名.歌曲名.时长.缩