nostra13 Imageloader是github上安卓ImageLoader类项目star数最多的开源项目。最近几期会带来ImageLoader的详细分析。
第一期:ImageLoader内存缓存原理解析
大家使用ImageLoader这类开源图片加载库的原因主要是普通的图片的处理方法很容易造成OOM,而使用良好的开源库可以有效避免这个问题。所以ImageLoader中的缓存机制就非常重要了。
其实ImageLoader中的缓存机制很简单,但很实用--加载图片的时候把图片根据一定的规则存到缓存中,在下次加载的时候优先获取缓存中的图片,这样可以快速的重载图片。并且根据一定的规则,缓存也能很好地自我管理,确保OOM不会轻易出现。
如图是ImageLoader的cache文件包,ImageLoader已经提供了多种缓存的方案供选择。
一、MemoryCache抽象类 (内存缓存)
1.BaseMemoryCache--内存缓存基类(抽象类)
查看MemoryCache接口的方法可以知道这个接口提供的是数据存储的基本功能(get,put,remove等)。
而BaseMemoryCache是一个抽象类,实现了MemoryCache
BaseMemoryCache提供了softmap(HashMap对象)来持有图片的弱引用
通过子类实现createReference方法,创建相应的弱引用
相应的get、put等方法,就是对softmap进行增删修改以达到存储图片引用的目的
注意,BaseMemoryCache中只会存储图片的弱引用。
2.LimitedMemoryCache--可限制的内存缓存基类(抽象类)
LimitedMemoryCache用强引用和弱引用存储图片,在限制的内存空间之内存储图片使用强引用,超过了限制的空间之后就使用弱引用,让系统自动回收。
LimitedMemoryCache提供一个List存储Bitmap,这样就将Bitmap的强引用存储到内存中。
put方法的原理是如果新的图片加入后内存超过限制的大小,则根据removeNext()的规则删除之前存储的图片,直到内存不超过限制大小,再存储新的图片。
removeNext()是一个抽象方法,这样就可以制定具体地规则去删除不需要存储的图片。
二、MemoryCache具体实现
1.FIFOLimitedMemoryCache
FIFOLimitedMemoryCache继承自LimitedMemoryCache,特性是当内存超过限制大小时,根据FIFO(先入先出)规则删除旧图片
FIFOLimitedMemoryCache使用LinkedList存储图片,在removeNext()中每次都删除List中的第一个元素就实现了FIFO
2.FuzzyKeyMemoryCache
FuzzyKeyMemoryCache会根据你传入的匹配规则(Comparator),在每次添加一张图片到内存的时候,根据匹配规则删除一张匹配到key的图片。
根据Comparator进行key的模糊匹配
ImageLoader提供了一种默认的匹配--匹配图片的url
3.LargestLimitedMemoryCache
LargestLimitedMemoryCache的规则是当新加图片后存储空间大于限制空间时,优先删除的是已经存储图片中的内存占用最大的那张图片。
LargestLimitedMemoryCache提供一个HashMap存储了该图片(key)相应的内存大小(value)。
然后在removeNext()中,每次遍历这个map找出最大的那张图片并删除。
4.LimitedAgeMemoryCache
LimitedAgeMemoryCache的规则是根据图片存入内存的时间判断是否需要删除这个图片。
使用HashMap保存图片存储的时间
在调用get方法获取内存中图片时,如果间隔时间大于设定的时间,则将这个图片从内存中删除
5.UsingFreqLimitedMemoryCache
UsingFreqLimitedMemoryCache的规则是当新加入图片后的内存大于限制的内存时,优先删除的是使用次数最少的图片。
使用HashMap存储图片的使用次数
在每次get的时候都为这个图片的使用次数加1
在removeNext中,遍历usingCounts,删除使用次数最少的那张图片
6.WeakMemoryCache
WeakMemoryCache把所有的图片存储为弱引用(让系统自动去负责回收咯)
7.LruMemoryCache
LruMemoryCache在一个限制的空间内持有所有图片的强引用,每一次某图片被访问,它会被置于队列的顶端,当新加的图片超过限制空间的大小时,队列最尾的图片会被移除出内存。
实现lru功能的原理其实非常简单,就是使用了LinkedHashMap,在构造的时候第三个参数accessOrder非常重要,设置为true,则LinkedHashMap就会拥有lru的特性(如下图说明)。
8.LRULimitedMemoryCache
LRULimitedMemoryCache原理与LruMemoryCache基本类似,也是使用LinkedHashMap的特性实现lru功能。
然后在removeNext中只需要移出队列最先的图片即可
以上就是ImageLoader内存缓存的基本特性和功能原理。了解了这些特性后,如果自己有新的更复杂的需求,就可以很方便地写出自己需要的类,去根据需求实现内存缓存的优化。
点击原文跳转到原github