Glide活跃活动缓存:activeResources:ActiveResources
。 活跃缓存他是没有大小限制的,有本事的话你可以无限往里面塞数据。来看下他的类:
1 2 3 4 final class ActiveResources { final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>(); private final ReferenceQueue<EngineResource<?>> resourceReferenceQueue = new ReferenceQueue<>(); }
数据是被保存到activeEngineResources这个HashMap里面。这个map是没容量限制的。我们可以看到他的key是一个key对象,他的键值是一个弱引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static final class ResourceWeakReference extends WeakReference <EngineResource <?>> { final Key key; final boolean isCacheable; Resource<?> resource; ResourceWeakReference( @NonNull Key key, @NonNull EngineResource<?> referent, @NonNull ReferenceQueue<? super EngineResource<?>> queue, boolean isActiveResourceRetentionAllowed) { super (referent, queue); this .key = Preconditions.checkNotNull(key); this .resource = referent.isMemoryCacheable() && isActiveResourceRetentionAllowed ? Preconditions.checkNotNull(referent.getResource()) : null ; isCacheable = referent.isMemoryCacheable(); } } }
为什么要用弱引用呢。我们知道弱引用有一个特性。在jvm触发垃圾回收的时候会回收掉弱引用。这也就是为什么glide在活动缓存里面没有设置容量大小限制的原因,因为他很容易就被全部干掉。 现在来看下活动缓存是怎么塞数据的:
1 2 3 4 5 6 7 8 9 10 11 synchronized void activate (Key key, EngineResource<?> resource) { ResourceWeakReference toPut = new ResourceWeakReference( key, resource, resourceReferenceQueue, isActiveResourceRetentionAllowed); ResourceWeakReference removed = activeEngineResources.put(key, toPut); if (removed != null ) { removed.reset(); } }
在塞数据的时候,如果存在同名的key,那么就会把上一个键值给重置掉。
这里还需要说一点,Glide监听了gc操作,那他是怎么监听的呢,就是通过弱引用里的ReferenceQueue来监听的:
1 2 3 4 5 6 7 8 9 10 11 void cleanReferenceQueue () { while (!isShutdown) { try { ResourceWeakReference ref = (ResourceWeakReference) resourceReferenceQueue.remove(); cleanupActiveReference(ref); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
开启了个线程无限循环,用来监听ResourceQueue的移除操作。当触发了gc就会,我们的ResourceQueue.remove就会收到反馈,然后删除了hasmap里面的值,然后如果我们开启了内存缓存,这个时候从活动缓存里面移除的数据会被添加到内存缓存里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void cleanupActiveReference (@NonNull ResourceWeakReference ref) { synchronized (this ) { activeEngineResources.remove(ref.key); if (!ref.isCacheable || ref.resource == null ) { return ; } } EngineResource<?> newResource = new EngineResource<>( ref.resource, true , false , ref.key, listener); listener.onResourceReleased(ref.key, newResource); } public void onResourceReleased (Key cacheKey, EngineResource<?> resource) { activeResources.deactivate(cacheKey); if (resource.isMemoryCacheable()) { cache.put(cacheKey, resource); } else { resourceRecycler.recycle(resource, false ); } }
内存缓存的知识后面再讲,现在需要知道的是,活动缓存里面的数据会被添加到内存缓存里面。