概述
有看过UIL源码的人都应该知道,库中缓存使用了策略模式来对bitmap进行缓存。这次来单独来分析其中的内存缓存策略
内存缓存
接口:
- MemoryCacheAware:底层接口,里面定义了基本的缓存操作方法
- MemoryCache:单纯继承了MemoryCacheAware接口
抽象类:
- BaseMemoryCache:实现了MemoryCahce,运用弱引用包装Bitmap后缓存存在HashMap中。同时也实现了MemoryCacheAware中的接口的方法
- LimitedMemoryCache:这个类继承BaseMemoryCahce,并在类中扩展了一级强引用缓存,也就是说LimitedMemoryCache是拥有双级缓存的(强引用缓存,弱引用缓存)。
- LimitedMemoryCache会限制内存的缓存大小,当达到缓存达到最大的内存缓存时,会移除缓存,至于移除的策略,库中有提供几个实现策略。
具体实现类:
- WeakMeoryCache:
|
|
WeakMemoryCache是继承自BaseMemoryCache,并且只是重写了createReference,所有WeakMemoryCache只有弱引用的缓存。
- LruMemoryCache:
|
|
LruMemoryCache继承自MemoryCache,因此只有强引用的缓存,LruMemoryCache移除缓存的策略是使用最近最少使用算法,即每次通过get得到的Bitmap都会放在队列头,移除的时候就会先从队列尾移除,这样就保证了最少使用的最先被移除
- LimitedAgeMemoryCache:
|
|
- LimitedAgeMemoryCache是MemoryCache的装饰类,也就是说LimitedAgeMemoryCache可以装饰实现了MemoryCache接口的类,比如LruMemoryCache。那么装饰的新功能是什么?
通过上面源码,可以清楚的得出,LimitedAgeMemoryCache是通过判断Bitmap的缓存时间是否超过在初始化传入时的缓存最大时间。超过的话就从内存中移除。
FuzzyKeyMemoryCache:
|
|
- FuzzyKeyMemoryCache也是继承自MemoryCache,同时也是MemoryCache的装饰类,装饰的新功能是:
当添加Bitmap进缓存时,如果添加进去的key跟之前添加过的key值相同的话,从内存移除之前key值对应的Bitmap,添加新传进来的Bitmap到内存。至于key相同的标准是什么,这个得根据自身的需求在重写Comparator对象并在初始化的时候传入。
UsingFreqLimitedMemoryCache:
|
|
- UsingFreqLimitedMemoryCache继承自LimitedMemoryCache,所以他拥有双级缓存用能(强弱引用缓存)。
UsingFreqLimitedMemoryCache的移除缓存的策略:每次使用get获得Bitmap时都会记录Bitmap使用的次数。要移除时,移除使用最少的次数的Bitmap,移除的只是强引用的缓存,弱引用中的缓存并不一定有被移除
LRULimit
|
|
LRULimitedMemoryCache继承自LimitedMemoryCache,同样也是具有两级缓存。而移除的策略是lru算法,这里不多分析。
LargestLimitedMemoryCache
|
|
LargestLimitedMemoryCache继承自LimitedMemoryCache,拥有双级缓存。移除缓存的策略是移除占内存最大的Bitmap
- FIFOLimitedMemoryCache
|
|
同理也是具有双级缓存功能,移除缓存的策略是移除头部的Bitmap
内存缓存策略总结:
类库中提供的三个接口:
- MemoryCache:实现该接口的类只有强引用的缓存功能
- BaseMemoryCache:实现该接口的类只有弱引用的缓存功能
- LimitedMemoryCache:实现该类的拥有两级缓存功能(强弱引用功能)
库中针对这三个接口,都给出了具体的实现类,我们可以根据自己的需求来设置缓存策略,默认的是LruMemoryCache
- 关于双级缓存:实现了LimitMemoryCache的类都具有双级缓存,但是为什么要使用双级缓存?
- 理解:缓存内存的最大值是固定的,超过这个值后,我们就得从内存中移除Bitmap,但是我们有时不是想要移除,只是内存不足了,我们被迫移除了Bitmap,所以增加了一级强引用的缓存,当内存不足 时,首先移除强引用的Bitmap,弱引用并没有被移除。这样下次如果请求相同的Bitmap时,就可以从弱引用的缓存中取出。但是这样做也有缺点,牺牲了内存。
- 总体说就是双级缓存就是通过牺牲内存来提高响应速度。
- 如果觉得库中提供给我们的策略不符合自己的业务需求的话,可以根据自己的业务需求来定制缓存策略。