Glide中的活跃活动缓存理解

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
//ActiveResouces.java

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
// ActiveResources.java
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
//ActiveResources.java
void cleanupActiveReference(@NonNull ResourceWeakReference ref) {
synchronized (this) {
activeEngineResources.remove(ref.key);

if (!ref.isCacheable || ref.resource == null) {
return;
}
}
EngineResource<?> newResource =
new EngineResource<>(
ref.resource, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ false, ref.key, listener);
listener.onResourceReleased(ref.key, newResource);
}

// Engine.java
public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
activeResources.deactivate(cacheKey);
if (resource.isMemoryCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource, /*forceNextFrame=*/ false);
}
}

内存缓存的知识后面再讲,现在需要知道的是,活动缓存里面的数据会被添加到内存缓存里面。