universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法
在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, new ImageViewAware(imageView), options, null, null);
}
会有ImageAware接口的一个实例化,这个默认的实例化有个重要的参数 :checkActualViewSize 具体说明如下
public ViewAware(View view) {
this(view, true);
} /**
* Constructor
*
* @param view {@link android.view.View View} to work with
* @param checkActualViewSize <b>true</b> - then {@link #getWidth()} and {@link #getHeight()} will check actual
* size of View. It can cause known issues like
* <a href="https://github.com/nostra13/Android-Universal-Image-Loader/issues/376">this</a>.
* But it helps to save memory because memory cache keeps bitmaps of actual (less in
* general) size.
* <p/>
* <b>false</b> - then {@link #getWidth()} and {@link #getHeight()} will <b>NOT</b>
* consider actual size of View, just layout parameters. <br /> 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>(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(, ) // max width, max height
.threadPoolSize()//线程池内加载的数量
.threadPriority(Thread.NORM_PRIORITY - ) //降低线程的优先级保证主UI线程不受太大影响
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache( * * )) //建议内存设在5-10M,可以有比较好的表现
.memoryCacheSize( * * )
.discCacheSize( * * )
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.discCacheFileCount() //缓存的文件数量
.discCache(new UnlimitedDiscCache(cacheDir))
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.imageDownloader(new BaseImageDownloader(getApplicationContext(), * , * )) // 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()//载入图片前稍做延时可以提高整体滑动的流畅度
.build();
滑动时禁止加载也可以有效的提高表现
setOnScrollListener(new PauseOnScrollListener(imageLoader, true, true));//两个分别表示拖动下拉条和滑动过程中暂停加载
最后就是在getview中,例行的viewholder保存状态之外,将URL存入imageview的tag中,通过对比URL值来减少UIL的display次数以提高表现
UIL是个非常不错的图片加载类的第三方库,可以帮我们在开发过程中省不少事,不过如果想用好也需要自己真正的去研究下
参考资料:
https://github.com/nostra13/Android-Universal-Image-Loader/issues/376
https://github.com/nostra13/Android-Universal-Image-Loader/wiki/Task-flow
universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法
universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法的更多相关文章
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...
- Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法
Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法 2014-03-27 11:44:46| 分类: Easy UI|举报|字号 订阅 可以使用$.parser.pa ...
- log4j中Spring控制台输出Debug级信息过多解决方法
log4j中Spring控制台输出Debug级信息过多解决方法 >>>>>>>>>>>>>>>>> ...
- MySQL中遇到的几种报错及其解决方法
MySQL中遇到的几种报错及其解决方法 1.[Err] 1064 - You have an error in your SQL syntax; check the manual that corre ...
- Linux下Oracle中SqlPlus时上下左右键乱码问题的解决办法
window下的sqlplus可以通过箭头键,来回看历史命令,用起来非常的方便. 但是在Linux下,会出现各种乱码,非常不方便,如下图所示,每次打错一个字符就需要重新打一遍. 解决办法:rlwrap ...
- [datatable]关于在DataTable中执行DataTable.Select("条件")返回DataTable的解决方法
-- :09关于在DataTable中执行DataTable.Select("条件")返回DataTable的解决方法 在实际编程工程中,常常遇到这样的情况:DataTable并不 ...
- Eclipse中SVN修改的*星号没了,解决方法
Eclipse中SVN修改的*星号没了,解决方法 打开Preference 第一步:去掉外加的 ">" 第二步:勾选Outgoing changes 这样做之后," ...
- Python3中使用HTMLTestRunner报No module named 'StringIO'解决方法
今天在学习使用HTMLTestRunner生成测试报告时遇到一个报错,如图所示: 网上搜索了下“No module named 'StringIO'”解决方法,原来我用的是Python 3.X版本,而 ...
- 在MonoGame中SetRenderTarget会把后备缓冲区清除的解决方法
在MonoGame中SetRenderTarget会把后备缓冲区清除的解决方法: 在构造函数中添加事件:graphics.PreparingDeviceSettings += Graphics_Pre ...
随机推荐
- 使用python进行接口测试(二)
之前使用过urllib和urllib2做接口测试,在做的途中,感觉使用urllib2直接进行的get,post 请求并没有那么好用.作为测试人员,所需要的测试工具应当以方便为第一要务,测试的耗时只要是 ...
- 百度系统部 在 北京市海淀区西二旗首创空间大厦 招聘 Python-交付运维系统研发工程师 - 内推网(neitui.Me)
百度系统部 在 北京市海淀区西二旗首创空间大厦 招聘 Python-交付运维系统研发工程师 - 内推网(neitui.Me) 汪肴肴 (wa**@baidu.com) 发布了 Python-交付运维系 ...
- java,大数据批量插入、更新
public void exec(Connection conn){ try { conn.setAutoCommit(false); Long beginTime = System.currentT ...
- 小结OC中Retain cycle(循环引用)
retain cycle 的产生 说到retain cycle,首先要提一下Objective-C的内存管理机制. 作为C语言的超集,Objective-C延续了C语言中手动管理内存的方式,但是区别于 ...
- [原创作品]一个实用的js倒计时器 postby:zhutty.cnblogs.com
今天做了一个手机短信发送倒计时,额,就是每隔多长时间可以重新发送的功能.贡献出来给园有吐槽点评. //倒计时,time:时长(秒),scb:每秒回调,cb:计时完成回调 var timing = fu ...
- 【顽固BUG】Visual Studio 2013 + TestDriven.NET-3.8.2860_Personal_Beta 调用的目标发生了异常。
前言 突然怎么弄也无法断点调试了 输出如下: ------ Test started: Assembly: Server5.V2.dll ------ 调用的目标发生了异常. 而且网站运行提示: -- ...
- 通过代码设置radiobutton不同方位图标的两种方法
更换radiobutton中的图片在xml中很好设置,但对于初学者如何在代码中设置还是不容易找的.没法子,通过看原版api找到两个方法,setCompoundDrawables和setCompound ...
- window+Apache 配置虚拟主机(2)
1. 打开虚拟主机功能 2. 设置虚拟主机相应的文件夹 3. 将虚拟的域名绑定到127.0.0.1 4. 结果图: 记忆一下,突然感觉都忘记了!
- WinXP 无线提示“区域中找不到无线网络”的一种可能原因!
貌似WinXP还是无限经典,我也一直还在用,不知道哪天才会放弃.这次遇见的问题,或许也有XP爱好者也遇得见,记下点文字备忘.----------------------- 单调的切割线 ------- ...
- WebMagic的设计参考了业界最优秀的爬虫Scrapy
http://webmagic.io/docs/zh/posts/ch1-overview/thinking.html https://github.com/psvehla/liferay-sprin ...