Android开发中一定会遇到图片加载,图片缓存的问题。Universal-Image-Loader是我遇到过的比较不错的一个开源框架,是国外一个大牛写的,据说现在作者已经不维护了,下面就源码来学习一下,欢迎交流!
首先看源码目录结构
从目录中可见,Universal-Image-Loader(后面用UIL表示)提供了两种缓存方式,内存和磁盘。再来介绍一下UIL的缓存流程。
还是一张图。
①UI:请求数据,使用唯一的Key值索引Memory Cache中的Bitmap。
②内存缓存:缓存搜索,如果能找到Key值对应的Bitmap,则返回数据。否则执行第三步。
③硬盘存储:使用唯一Key值对应的文件名,检索SDCard上的文件。
④如果有对应文件,使用BitmapFactory.decode*方法,解码Bitmap并返回数据,同时将数据写入缓存。如果没有对应文件,执行第五步。
⑤下载图片:启动异步线程,从数据源下载数据(Web)。
⑥若下载成功,将数据同时写入硬盘和缓存,并将Bitmap显示在UI中。
上面片段摘自其他技术贴,应该都是浅显易懂。不过我来追加补充了解一下,加深认识。
首先是1的Key值,从代码中看Key值如何生成。
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
可见,memoryCacheKey和图片url本身以及要显示的目标大小作为唯一key。就是说就算同一张图片,只要显示为不同尺寸,也不是用的
同一个bitmap。
另外3中的从代码查看是直接用文件名检索而不是先通过唯一key。
聊完基本业务流程,就来谈谈UIL都提供了哪些缓存算法。再来看一张图
从图片可以看出,UIL提供的内存缓存算法比较丰富,有8种,磁盘缓存则只有2种。下面稍微介绍一下各自算法的大致意思。
1、FIFOlimitedMemoryCache
先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap。
2、FuzzyKeyMemoryCache
这个是内部使用,用于比较bitmap是否存在,有则移除。
3、LimitedMemeryCache
使用强引用和弱引用结合的缓存策略,cacheSize以内的为强引用,cacheSize以外的为弱引用。
4、LargestLimitedMemeryCache
当超过缓存限定值,先删除最大的bitmap对象。
5、LimitedAgeMemoryCache
当 bitmap加入缓存中的时间超过我们设定的值,将其删除。
6、LRULMemoryCache
使用的LRU算法,当有需要时最近最少使用bitmap从缓存中删除。
7、LRULimitedMemoryCache
这个也是使用的LRU算法,和LruMemoryCache不同的是,他缓存加入了弱引用。cacheSize以内的为强引用,cacheSize以外的为弱引用。
8、WeakMemoryCache
这个算法只使用了弱引用来作为缓存策略。
接下来就是磁盘缓存
imitedAgeDiscCache
设定文件存活的最长时间,当超过这个值,就删除该文件。
UnlimitedDiscCache
这个缓存类没有任何的限制。
介绍完上面的缓存算法之后,大家是否都看到了,强引用、软引用、弱引用等概念。现在就这三个再介绍介绍。
1.强引用
以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
2.软引用(SoftReference)
如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。
3.弱引用(WeakReference)
如果一个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
其实UIL这个框架的代码中可以看到很多Java的一些编程思想,设计模式等。但出于时间考虑,先写这些,后面有时间继续补充。