参考地址:http://www.cnblogs.com/kissazi2/p/3931400.html
参考地址:本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/26810303)
最近在做图片缓存,APP要加载大量图片,使用imageloader进行缓存,刚刚接触imageloader的我,对于缓存基本上一片空白,马上就百度一下,复制了一份使用缓存的代码,但是不符合我的需求,所以,我对它进行了改进。记录一下这次的经验,方便以后查找。
第一,要了解一下imageloader的缓存机制。原理示意图如下:
① UI:请求数据,使用唯一的Key值索引Memory Cache中的Bitmap。
② 内存缓存:缓存搜索,如果能找到Key值对应的Bitmap,则返回数据。否则执行第三步。
③ 硬盘存储:使用唯一Key值对应的文件名,检索SDCard上的文件。
④ 如果有对应文件,使用BitmapFactory.decode*方法,解码Bitmap并返回数据,同时将数据写入缓存。如果没有对应文件,执行第五步。
⑤ 下载图片:启动异步线程,从数据源下载数据(Web)。
⑥ 若下载成功,将数据同时写入硬盘和缓存,并将Bitmap显示在UI中。
下面来看一下我初始化imageloader的代码
<span style="font-size:12px;">ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
this)
.memoryCacheExtraOptions(720, 1280)
// default = device screen dimensions
.threadPoolSize(3)
// default
.threadPriority(Thread.NORM_PRIORITY - 1)
// default
.tasksProcessingOrder(QueueProcessingType.FIFO)
// default
.denyCacheImageMultipleSizesInMemory()
// .memoryCache(new WeakMemoryCache())
.memoryCache(new UsingFreqLimitedMemoryCache(2* 1024 * 1024))
.memoryCacheSize(2 * 1024 * 1024)
.memoryCacheSizePercentage(13)
// default
// .diskCache(new BaseDiskCache(cacheDir) {
.diskCache(mLruDiskCache)
// default
.diskCacheSize(50 * 1024 * 1024)
.diskCacheFileCount(100)
// .diskCacheFileNameGenerator(new Md5FileNameGenerator())
// default
.imageDownloader(
new BaseImageDownloader(getApplicationContext())) // default
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
.writeDebugLogs()
.build();
ImageLoader.getInstance().init(config);</span>
在这里,就不得不向大家介绍一下
强引用和
弱引用
强引用是指创建一个对象并把这个对象赋给一个引用变量, 强引用有引用变量指向时永远不会被垃圾回收。即使内存不足的时候宁愿报OOM也不被垃圾回收器回收,我们new的对象都是强引用
内存缓存
现在我们来看Universal-Image-Loader有哪些内存缓存策略
1. 只使用的是强引用缓存
- LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)
2.使用强引用和弱引用相结合的缓存有
- UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
- LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
- FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
- LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
- LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
3.只使用弱引用缓存
- WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)
上面介绍了Universal-Image-Loader所提供的所有的内存缓存的类,当然我们也可以使用我们自己写的内存缓存类,我们还要看看要怎么将这些内存缓存加入到我们的项目中,我们只需要配置ImageLoaderConfiguration.memoryCache(...),如下
<span style="font-size:12px;">ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
.memoryCache(new WeakMemoryCache())
.build(); </span>
硬盘缓存
接下来就给大家分析分析硬盘缓存的策略,这个框架也提供了几种常见的缓存策略,当然如果你觉得都不符合你的要求,你也可以自己去扩展
- FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
- LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
- TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
- UnlimitedDiscCache(这个缓存类没有任何的限制)
如果我们在ImageLoaderConfiguration中配置了diskCacheSize和diskCacheFileCount,他就使用的是LruDiscCache,否则使用的是UnlimitedDiscCache,在最新的源码中还有一个硬盘缓存类可以配置,那就是LimitedAgeDiscCache,可以在ImageLoaderConfiguration.diskCache(...)配置,代码如下
<span style="font-size:12px;">LruDiskCache mLruDiskCache = null;
try {
mLruDiskCache = new LruDiskCache(cacheDir, new Md5FileNameGenerator(), 2* 1024 * 1024);
} catch (Exception e) {
// TODO: handle exception
Log.e("Waring", "SD卡缓存失败");
}
finally{
Log.d("Waring", "SD卡缓存初建立");
}
ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
.diskCache(mLruDiskCache)
.diskCacheSize(50 * 1024 * 1024)
.diskCacheFileCount(100)
.build(); </span>
还有一点想提醒大家:大家在设置缓存后,一定要在options这个参数里面设置,如果不设置可能会没有效果!!!代码如下
<span style="font-size:12px;">public DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true).cacheOnDisk(true)
.bitmapConfig(Config.RGB_565)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT).build();</span>