Glide缓存分为两个方面内存缓存和磁盘缓存。
主要看一下内存缓存
GenericRequest调用onSizeReady函数,通过Engie.load加载图片.
load先从内存缓存中加载图片,有两个层级,一个是MemoryCache,一个是ActiveResouces。
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
内存缓存根据key加载图片。
有两个部分:
1、图片存到内存的;
2、怎样取内存中的图片。
1、 图片存到内存的过程
图片加载完成后才会缓存,首先要看一下加载过程(无缓存、无active )。
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(runnable);
这块有几个和加载相关的类:DecodeJob、EngineJob 、EngineRunnable
DecodeJob:图片原始数据加载、解码
EngineRunnable :一个中间类,DecodeJob和EngineJob的包装 ,调用DecodeJob加载图片数据,数据加载完成通知EngineJob。
EngineJob :处理DecodeJob的加载结果。
engineJob.start(runnable);提交EngineRunnable 给执行ExecutorService,EngineRunnable的Run方法执行decode():
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();
} else {
return decodeFromSource();
}
}
加载图片数据,加载图片数据完成后(EngineRunnable,Run方法)调用:
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
只看加载成功,调用onLoadComplete(EngineRunnable中):
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
onLoadComplete调用 manager.onResourceReady(resource);这个manager既是EngineJob
public EngineRunnable(EngineRunnableManager manager, DecodeJob<?, ?, ?> decodeJob, Priority priority) {
this.manager = manager;
this.decodeJob = decodeJob;
this.stage = Stage.CACHE;
this.priority = priority;
}
class EngineJob implements EngineRunnable.EngineRunnableManager,EngineJob 实现 EngineRunnable.EngineRunnableManager。
EngineJob 在onResourceReady中调用了
public void onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
加载图片数据不在UI线程,所以图片回调到ImageView时得切到UI线程。
MAIN_THREAD_HANDLER初始化(EngineJob ):
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
MAIN_THREAD_HANDLER 发送MSG_COMPLETE告知图片加载完成:
private static class MainThreadCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
EngineJob job = (EngineJob) message.obj;
if (MSG_COMPLETE == message.what) {
job.handleResultOnMainThread();
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
下面是缓存部分。
调用job.handleResultOnMainThread()三个主要功能:
a)回调Engine进行ActiveResouce资源缓存
b)回调给ImageView
c)进行MemoryCache
private void handleResultOnMainThread() {
if (isCancelled) {
resource.recycle();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
engineResource.acquire();
listener.onEngineJobComplete(key, engineResource);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
a)回调Engine进行ActiveResouce资源缓存,对应这行代码:
listener.onEngineJobComplete(key, engineResource);
listener在Engine构造方法初始化,
public void onEngineJobComplete(Key key, EngineResource<?> resource) {
Util.assertMainThread();
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null) {
resource.setResourceListener(key, this);
if (resource.isCacheable()) {
activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
}
}
// TODO: should this check that the engine job is still current?
jobs.remove(key);
}
b)回调给ImageView,对应
cb.onResourceReady(engineResource);
c)进行Memory缓存
,对应engineResource.release();
在a、b时进行active缓存、回调给ImageView时,进行引用计数engineResource.acquire();
在最后对资源进行释放,在引用计数为0时,对资源进行Memory缓存;
void release() {
if (acquired <= 0) {
throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
}
if (!Looper.getMainLooper().equals(Looper.myLooper())) {
throw new IllegalThreadStateException("Must call release on the main thread");
}
if (--acquired == 0) {
listener.onResourceReleased(key, this);
}
}
listener,在onEngineJobComplete中赋值 resource.setResourceListener(key, this)回调到Engine中进行内存缓存。
public void onResourceReleased(Key cacheKey, EngineResource resource) {
Util.assertMainThread();
activeResources.remove(cacheKey);
if (resource.isCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource);
}
}
2、
怎样取内存中的图片
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}