Glide生命周期管理
Glide缓存实现
二级内存缓存 + LRU磁盘缓存
弱引用实现
第一级实现:WeakReference + ReferenceQueue
ActiveResources
Map
ReferenceQueue
内部启动了一个监控GC回收资源的线程,调用resourceReferenceQueue的remove方法,阻塞住,当被ResourceWeakReference持有的对象可达性发生变化(即即将被GC前),会把对应的引用添加到resourceReferenceQueue队列,重新构建一个EngineResource对象,再次加入到LruCache中。
第二级实现:LruCache
Lru背景知识
缓存的⼤⼩有限,当缓存被⽤满时,哪些数据应该被清理出去,哪些数据应该被保留?这就 需要缓存淘汰策略来决定。常⻅的策略有三种:先进先出策略FIFO(First In,First Out)、 最少使⽤策略LFU(Least Frequently Used)、最近最少使⽤策略LRU(Least Recently Used)。
简单的LRU实现思路
维护⼀个有序单链表,越靠近链表尾部的结点是越早之前访问的。 当有⼀个新的数据被访问时,我们从链表头开始顺序遍历链表。
1.如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来 的位置删除,然后再插⼊到链表的头部。
2.如果此数据没有在缓存链表中,⼜可以分为两种情况:
如果此时缓存未满,则将此结点直接插⼊到链表的头部;
如果此时缓存已满,则链表尾结点删除,将新的数据结点插⼊链表的头部。
使用数组可以实现,但是无法达到O(1);
使用单向链表也可以实现,但是也无法达到O(1),因为get无法达到O(1)
想要get达到O(1),可以使用哈希表,但是想要将缓存命中的处于链表中间的节点移动到头部,然后将该节点前后的元素连接起来时,获取该节点前一个元素还得再遍历一遍,为解决这个问题,可以使用双向链表。
LinkedHashMap已经实现LRU
|
|
第三级实现
DiskLruCache
DiskLruCache的核心是journal文件,每次操作都会在journal文件中做一次记录。
写入缓存的时候会向journal文件写入一条以DIRTY开头的数据表示正在进行写操作,当写入完毕时,分两种情况:1、写入成功,会向journal文件写入一条以CLEAN开头的文件,其中包括该文件的大小。 2、写入失败,会向journal文件写入一条以REMOVE开头的文件,表示删除了该条缓存。也就是说每次写入缓存总是写入两条操作记录。
读取的时候,会向journal文件写入一条以READ开头的文件,表示进行了读操作
删除的时候,会向journal文件写入一条以REMOVE开头的文件,表示删除了该条缓存
通过journal就记录了所有对缓存的操作。并且按照从上到下的读取顺序记录了对所有缓存的操作频繁度和时间顺序。这样当退出程序再次进来调用缓存时,就可以读取这个文件来知道哪些缓存用的比较频繁了。然后把这些操作记录读取到集合中,操作的时候就可以直接从集合中去对应的数据了。
Glide并发管理
|
|
Glide加载缓存未命中的线程池会根据根据CPU的数量和Java虚拟机中可用的处理器数量来选择合适的线程数,但是最多不超过4;而加载缓存命中的图片的线程池默认大小为1.