universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法

原文转载:http://www.cnblogs.com/wuxilin/p/4333241.html

在listview/gridview中使用UIL来display每个item的图片,当图片数量较多需要滑动滚动时会出现卡顿,而且加载过的图片再次上翻后依然会重复加载(显示设置好的加载中图片)

最近在使用UIL遇到了这个问题,相信这个问题许多使用UIL的人都碰到过

现在把解决方法贴出来给有同样问题的朋友做参考

先看下UIL的工作流程

在已经允许内存,存储卡缓存的前提下,当一个图片被请求display时,首先要判断图片是否缓存在内存中,如果false则尝试从存储卡读取,如果依然不存在最后才从网络地址下载

从内存读取的速度最快,存储卡次之,在我们滚动listview的时候,如果是从内存加载图片则会显得非常流畅,如果是存储卡就会先出现载入中图片然后再显示实际图片

我们通常认为已经读过一次的图片自然将会加入内存缓存中,那么下一次读取将是直接从内存中读取,但是实际上载入过的图片在滑动出屏幕再滑动回来后依然会再次从存储卡读取,这主要是UIL的缓存策略引起的一个"疑似BUG"

查看UIL的源码,displayImage函数

public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) {

displayImage(uri,newImageViewAware(imageView), options,null,null);

}

会有ImageAware接口的一个实例化,这个默认的实例化有个重要的参数 :checkActualViewSize 具体说明如下

public ViewAware(View view) {

this(view,true);

}

/**

* Constructor

*

*@param view{@linkandroid.view.View View} to work with

*@param checkActualViewSize true - then {@link#getWidth()} and {@link#getHeight()} will check actual

*size of View. It can cause known issues like

*this.

*But it helps to save memory because memory cache keeps bitmaps of actual (less in

*general) size.

*

*false - then {@link#getWidth()} and {@link#getHeight()} will NOT

*consider actual size of View, just layout parameters.
If you set 'false'

*it's recommended 'android:layout_width' and 'android:layout_height' (or

*'android:maxWidth' and 'android:maxHeight') are set with concrete values. It helps to

*save memory.

*/

public ViewAware(View view,boolean checkActualViewSize) {

if(view ==null)throw new IllegalArgumentException("view must not be null");

this.viewRef =new WeakReference(view);

this.checkActualViewSize = checkActualViewSize;

}

这个参数会影响缓存时的key名称,当图片第一次缓存时,当时图片并未下载,自然无法获得图片的长宽尺寸,这时UIL会使用配置预设的maxwidth和maxheight为长宽,缓存的key名称为类似这样:url_widthxheight

在checkActualViewSize设置为true时,第二次载入图片的view将会读取view的长宽,这时的长宽会是图片的实际尺寸,相应的生成的缓存key名称也会变成url_realwidthxrealheight,这个名称同之前缓存的不同,因此也当然不能在缓存查询中命中

所以最后就需要再次从存储中加载图片,并以新的keyname再存一份副本到内存中

解决方法有两个:

1)设置imageview的layout_width和layout_height为实际图片长宽(假如你的图片都是固定尺寸的,这样做就OK了)

2)display的方法修改一下,不直接display imageview改为ImageAware,类似

ImageAware imageAware =new ImageViewAware(imageView,false);

imageLoader.displayImage(imageUri, imageAware);

显式的将checkActualViewSize设为false, 这样图片的缓存也将只会保存一个副本,保证第二次查询时可以直接命中

按上述方法设置之后一般来说在listview/gridview滑动时图片效果基本没什么大问题了,但是还有些额外设置也许也是大家需要注意的

首先是config的初始化

File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "imageloader/Cache");//缓存文件的存放地址

ImageLoaderConfiguration config =new ImageLoaderConfiguration

.Builder(getApplicationContext())

.memoryCacheExtraOptions(480, 800)// max width, max height

.threadPoolSize(3)//线程池内加载的数量

.threadPriority(Thread.NORM_PRIORITY - 2)//降低线程的优先级保证主UI线程不受太大影响

.denyCacheImageMultipleSizesInMemory()

.memoryCache(newLruMemoryCache(5 * 1024 * 1024))//建议内存设在5-10M,可以有比较好的表现

.memoryCacheSize(5 * 1024 * 1024)

.discCacheSize(50 * 1024 * 1024)

.discCacheFileNameGenerator(newMd5FileNameGenerator())

.tasksProcessingOrder(QueueProcessingType.LIFO)

.discCacheFileCount(100)//缓存的文件数量

.discCache(newUnlimitedDiscCache(cacheDir))

.defaultDisplayImageOptions(DisplayImageOptions.createSimple())

.imageDownloader(newBaseImageDownloader(getApplicationContext(), 5 * 1000, 30 * 1000))// connectTimeout (5 s), readTimeout (30 s)

.writeDebugLogs()// Remove for release app

.build();

然后是option的设置

options =new DisplayImageOptions.Builder()

.showStubImage(R.drawable.default_cover)

.showImageForEmptyUri(R.drawable.default_cover)

.showImageOnFail(R.drawable.default_cover)

.cacheInMemory(true)

.cacheOnDisc(true)

.imageScaleType(ImageScaleType.NONE)

.bitmapConfig(Bitmap.Config.RGB_565)//设置为RGB565比起默认的ARGB_8888要节省大量的内存

.delayBeforeLoading(100)//载入图片前稍做延时可以提高整体滑动的流畅度

.build();

滑动时禁止加载也可以有效的提高表现

setOnScrollListener(new PauseOnScrollListener(imageLoader,true,true));//两个分别表示拖动下拉条和滑动过程中暂停加载

最后就是在getview中,例行的viewholder保存状态之外,将URL存入imageview的tag中,通过对比URL值来减少UIL的display次数以提高表现

UIL是个非常不错的图片加载类的第三方库,可以帮我们在开发过程中省不少事,不过如果想用好也需要自己真正的去研究下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容