UniversiallImageLoader源码阅读理解(一)
来源:互联网 发布:oecd下载数据 编辑:程序博客网 时间:2024/05/19 13:57
ImageLoader内存缓存模块:
最底层有接口 public interface MemoryCache;
然后 public abstract class BaseMemoryCache implements MemoryCahce,即BaseMemoryCache 实现MemoryCache接口;
还有 public abstract class LimitedMemoryCache extends BaseMemoryCache,即LimitedMemoryCache 继承BaseMemoryCache;
实际中可以扩展的内存缓存方案有:
1. FIFOLimitedMemoryCache extends LimitedMemoryCache
先进先出缓存,最大内为16M,可以手动设置超过16M内存,会有警告提示。
由于FIFOLimitedMemoryCache extends LimitedMemoryCache extends BaseMemoryCache,在源码中发现最终的BitMap缓存再三个线程安全的LinkedList中。
最内层的private final Map<String, Reference<Bitmap>>softMap= Collections.synchronizedMap(newHashMap<String, Reference<Bitmap>>());
中间的private final List<Bitmap>hardCache= Collections.synchronizedList(newLinkedList<Bitmap>());
最外层的private final List<Bitmap>queue= Collections.synchronizedList(newLinkedList<Bitmap>());
Collections.synchronizedList包裹普通List'提供线程安全机制,但是仅提供方法的线程安全,List本身被访问还需要其他控制。
FIFOLimitedMemoryCache 中重写了createReference方法返回为弱引用,可知FIFOLimitedMemoryCache 保存弱在弱引用。
FIFOLimitedMemoryCache 的put方法会将图片同时保存在两个LinkedList(queue 与hardCache)和应HashMap中(softMap)。为什么这样设计?待研究!
在LimitedMemoryCache 的put方法中最终会计算当前要保存的图片占有大小+现有的内存图片缓存大小是否大于创建FIFOLimitedMemoryCache 对象时设置的最大值,
如果是持续执行removeNext方法中的queue.remove(0); 直到上述条件为否,可以看出remove(0)实际就是删除最先进入queue 的图片,此处实现了先进先出的目标。而remove(0)的同时执行hardCache.remove(removedValue),但是此操作没有删除softMap 中的图片缓存,这是几个意思?待研究!
FIFOLimitedMemoryCache 中的remove方法会正常的删除queue 、hardCache 、softMap 的图片缓存。
2.LargestLimitedMemoryCache extends LimitedMemoryCache
此内存缓存策略是内存不足时删除缓存中占内存最大的图片
继承关系:LargestLimitedMemoryCache extends LimitedMemoryCache extends BaseMemoryCache
LargestLimitedMemoryCache中有新的定义private finalMap<Bitmap, Integer>valueSizes= Collections.synchronizedMap(newHashMap<Bitmap, Integer>());
内部两层softMap和hardCache由于继承关系用来保存图片缓存。
LargestLimitedMemoryCache的关键也在removeNext方法,此处for循环查找valueSizes集合中占内存最大的图片,然后删除。
其他 hardCache 及softMap 同 FIFOLimitedMemoryCache 中操作
3.LRULimitedMemoryCache extends LimitedMemoryCache
此内存缓存时使用最近最少使用算法删除缓存中最近最少使用的图片缓存
LRULimitedMemoryCache中定义了用来保存图片缓存的LinedHashMap
private final Map<String, Bitmap>lruCache= Collections.synchronizedMap(newLinkedHashMap<String, Bitmap>(INITIAL_CAPACITY,LOAD_FACTOR,true));
此处不需要主动去实现LRU算法,因为LinkedHashMap的底层是一个双向链表,调用LinkedhashMap方法的get()方法取得查找的元素后,将最新访问的元素添加到双向链表的表头,并从原来的位置删除。故LRULimitedMemoryCache方法,只需要做的就是在缓存爆满前删除链表表尾的一个元素即可。
hardCache 及 softMap 操作 同上
4.UsingFreqLimitedMemoryCache extends LimitedMemoryCache
此内存缓存方案是:删除使用次数最少的图片缓存
UsingFreqLimittedMemoryCache中定义了 private finalMap<Bitmap, Integer>usingCounts= Collections.synchronizedMap(newHashMap<Bitmap, Integer>());
形似LargestLimitedMemoryCache中定义的 valueSize 但是此处的Integer保存的是 对应图片的在get方法中被命中的次数,所以代码中的get方法在每次命中缓存后,总会对usingCounts中的Integer进行+1操作。
UsingFreqLimitedMemory中的removeNext方法及其他逻辑同LatgestLimitedMemoryCache
5.FuzzyKeyMemoryCache implements MemoryCache
看名字意思关键字内存缓存,MemoryCache的装饰模式,没有过多逻辑,注释提示此方案为内部使用,不需要使用。
基本逻辑是初始化传入装饰对象MemoryCache,及接口Comparator。
主要逻辑集中在是put(String key, Bitmap value)方法,遍历MemoryCache中的缓存,找到key值相同的value执行remove操作再将最新的value执行put操作
6.LimitedAgeMemoryCache implements MemoryCache
此内存缓存方案为设置图片缓存在内存中的生命周期。
在LimitedAgeMemoryCache中声明应用于保存图片缓存生命周期的HashMap:
private final Map<String, Long>loadingDates= Collections.synchronizedMap(newHashMap<String, Long>());
在缓存类初始化时设定图片缓存生命周期。
put方法中保存图片缓存同时保存当前系统时间;在get方法中判断当前需要命中的图片缓存生命周期是否已经结束,如果是直接冲缓存中ewmove。
因为此缓存方案代码中先执行缓存图片的生命周期判断然后才从内存中获取图片缓存,所以有可能获取到空。
7.LruMemoryCache implements MemoryCache
此内存缓存方案为最近最少使用算法删除法,图片保存方式与LRULimitedMemoryCache一致,都采用了LinkedhashMap的特性。
但是与LRULimitedMemoryCache不同的是LruMemoryCache使用强引用,而LRULimitedMemoryCache使用弱引用。
8.WeakMemory extneds BaseMemoryCache
仅继承BaseMemoryCache,实现createReference方法,将底层保存图片的LinkedHashMap所保存的对象设置为弱引用。
附:
强引用:不会被GC线程回收的
软引用:在内存不足时可能会被回收(英威GC线程优先级很低,所以软引用也不一定会被回收)
弱引用:只要GC线程开始执行,就一定会被回收
虚引用:和没有引用一样,主要用来跟踪垃圾回收器回收的活动
GC常用算法:
1.标记清除法
将需要回收的对象标记,然后回收。效率不高,产生内存碎片
2.复制算法
将内存分为两块,一块内存即将饱和时将所有存活对象复制到另一块内存,然后清空当前内存。运行效率高,内存空间使用效率低。
3.标记整理法
标记需要回收的对象,然后将存活的对象移动到一端,然后清理边界意外的内存。
4.分代收集算法
一般都分为Young代与Old代,每个世代根据情况使用不同的算法。
更多java内存回收资料 http://blog.jobbole.com/37273/
- UniversiallImageLoader源码阅读理解(一)
- Android源码阅读与理解(一):开篇
- Tiny-Spring源码阅读(一)IOC的理解
- 源码阅读(一)
- 源码阅读(一)
- WINVNC源码阅读(一)
- Hadoop源码阅读(一)
- eoe源码阅读(一)
- mybatis源码阅读(一)
- 源码阅读(一)RadialTransitionExample
- SDWebImage 源码阅读(一)
- 源码阅读--RxJava(一)
- YYModel源码阅读(一)
- live555源码阅读(一)
- kubernetes源码之watch包watch.go阅读理解一
- ThinkPHP源码阅读理解
- winvnc源码阅读笔记(一)---------线程
- 源码阅读笔记 Activity(一)
- priority_queue的用法
- Android购物车页面单个商家可单独结算
- Ubuntu16上Nginx安装教程
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
- Mysql的数据备份类型——物理备份与逻辑备份,全量与增量
- UniversiallImageLoader源码阅读理解(一)
- 带你深入理解STL之Vector容器
- 日历--给input赋值
- [Kafka]_1
- RabbitMQ消息队列(五):Routing 消息路由[转]
- 课上问题
- MongoDB分片集群与复制集
- 51Nod 1631 小鲨鱼在51Nod小学 【 扫描线 】
- java 动态创建对象