在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中滚动时重复加载图片的问题及解决方法的更多相关文章

  1. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  2. Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法

    Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法 2014-03-27 11:44:46|  分类: Easy UI|举报|字号 订阅     可以使用$.parser.pa ...

  3. log4j中Spring控制台输出Debug级信息过多解决方法

    log4j中Spring控制台输出Debug级信息过多解决方法 >>>>>>>>>>>>>>>>> ...

  4. MySQL中遇到的几种报错及其解决方法

    MySQL中遇到的几种报错及其解决方法 1.[Err] 1064 - You have an error in your SQL syntax; check the manual that corre ...

  5. Linux下Oracle中SqlPlus时上下左右键乱码问题的解决办法

    window下的sqlplus可以通过箭头键,来回看历史命令,用起来非常的方便. 但是在Linux下,会出现各种乱码,非常不方便,如下图所示,每次打错一个字符就需要重新打一遍. 解决办法:rlwrap ...

  6. [datatable]关于在DataTable中执行DataTable.Select("条件")返回DataTable的解决方法

    -- :09关于在DataTable中执行DataTable.Select("条件")返回DataTable的解决方法 在实际编程工程中,常常遇到这样的情况:DataTable并不 ...

  7. Eclipse中SVN修改的*星号没了,解决方法

    Eclipse中SVN修改的*星号没了,解决方法 打开Preference 第一步:去掉外加的 ">" 第二步:勾选Outgoing changes 这样做之后," ...

  8. Python3中使用HTMLTestRunner报No module named 'StringIO'解决方法

    今天在学习使用HTMLTestRunner生成测试报告时遇到一个报错,如图所示: 网上搜索了下“No module named 'StringIO'”解决方法,原来我用的是Python 3.X版本,而 ...

  9. 在MonoGame中SetRenderTarget会把后备缓冲区清除的解决方法

    在MonoGame中SetRenderTarget会把后备缓冲区清除的解决方法: 在构造函数中添加事件:graphics.PreparingDeviceSettings += Graphics_Pre ...

随机推荐

  1. RequireJS 2.0 新特性

    就在前天晚上RequireJS发布了一个大版本,直接从version1.0.8升级到了2.0.随后的几小时James Burke又迅速的将版本调整为2.0.1,当然其配套的打包压缩工具r.js也同时升 ...

  2. 使用nvm来管理nodejs版本

    nvm 是 Mac 下的 node 管理工具,有点类似管理 Ruby 的 rvm,如果是需要管理 Windows 下的 node,官方推荐是使用 nvmw 或 nvm-windows .nvm主要用来 ...

  3. [原创]安卓使用Termux做渗透测试(演示sqlmap安装,并附上一个神器)

    由于手机kali太大,并且MIUI8+Android6.0的我.用手机kali不是太方便(懒得捣鼓),所以另找道路,用手机作渗透测试. 1.下载一个Termux,并授予ROOT权限. 2.打开之后输入 ...

  4. Eclipse设置保存时自动给变量加final

    也是针对checkstyle的,在代码检查规范时,所有的变量必须是final.为了解决这个问题,通过以下的设置可以在eclipse保存时,自动给没有加final的变量加上final. Window-& ...

  5. Nyoj 43 24 Point game 【DFS】

    24 Point game 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描写叙述 There is a game which is called 24 Point game ...

  6. 搭建Windows下Java Web开发环境

      概要 1.SSH开发相关软件及开发包下载2.软件安装及相关设置3.最简单的Web程序 1.软件下载 在D盘建一个目录JavaTools,用来存放下载的软件和开发包.(本教程将使用D盘,你也可以使用 ...

  7. 数据持久化之CoreData

    再次回归博客园, 已经实属不易了, 面临这近期忙忙碌碌的项目开发, 虽然并不是完全的没有闲暇时间, 但是怎么说呢, 也有着各种的无奈与曲折, 面临这产品需求的不断变化和页面的不断更新, 对于一个程序员 ...

  8. Myself

    每次过来写博客,一定是遇到什么问题,并且自己还解决不来. 并不是单纯的安静下来书写心得体会-->讨厌之余都有点看不起自己. 闲话少说,回归正题. C语言之于我可是骄傲与挫败并存. 当我做程式遇到 ...

  9. linux目录权限小记

    r : 拥有读取目录结构列表的权限 x:拥有进入此目录的权限 w: 1: 建立新的档案和目彔: 2删除已经存在的档案和目录(无论该档案的权限为何!) 3能够重命名档案和目录: 4 能够移动目录里面的 ...

  10. Xml读取异常--Invalid byte 1 of 1-byte UTF-8 sequence

    xml读取异常Invalid byte 1 of 1-byte UTF-8 sequence org.dom4j.DocumentException: Invalid byte 1 of 1-byte ...