入口方法是Enigine.load()
- 从内存中加载——loadFromMemory()
- 从磁盘或网络加载
public <R> LoadStatus load(/***/) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
EngineKey key =
keyFactory.buildKey(//***);
EngineResource<?> memoryResource;
synchronized (this) {
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
return waitForExistingOrStartNewJob(
//***)
}
}
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
return null;
}
内存加载的过程:
- 从内存中正在使用的资源中加载
- 从内存缓存中加载
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
return active;
}
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
return cached;
}
return null;
}
从正在使用的资源中加载:
ActivityResources是一个资源管理类,将当前正在使用的资源进行了保存(用WeakReference持有资源,并保存到Map中)。
private EngineResource<?> loadFromActiveResources(Key key) {
EngineResource<?> active = activeResources.get(key);
if (active != null) {
active.acquire();
}
return active;
}
从缓存中加载:
从MemoryCache中获取缓存,如果有,则放入给该资源引用计数加1,并放入ActivityResources中。
private EngineResource<?> loadFromCache(Key key) {
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
cached.acquire();
activeResources.activate(key, cached);
}
return cached;
}
private EngineResource<?> getEngineResourceFromCache(Key key) {
Resource<?> cached = cache.remove(key);
final EngineResource<?> result;
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
// Save an object allocation if we've cached an EngineResource (the typical case).
result = (EngineResource<?>) cached;
} else {
result =
new EngineResource<>(
cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
}
return result;
}
如果内存中没有,需要从磁盘缓存或者网络中加载,主要逻辑在waitForExistingOrStartNewJob()中:
- 当前是否已有该资源的加载任务,如果有,则添加一个回调,避免重复加载;
- 启动一个EngineJob用于管理加载的回调,实际的加载工作在DecodeJob中完成
private <R> LoadStatus waitForExistingOrStartNewJob(/**/) {
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
return new LoadStatus(cb, current);
}
EngineJob<R> engineJob =
engineJobFactory.build(/**/);
DecodeJob<R> decodeJob = decodeJobFactory.build(/**/);
jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
可以看下EngineJob.start() 的实现——将DecodeJob放入线程池等待执行:
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
executor.execute(decodeJob);
}
DecodeJob实现了Runnable接口,重点看它实现的run()方法:
- 判断是否已取消
- 调用runWrapped()方法执行状态转换
- 一些异常处理和回调执行
public void run() {
//***
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (CallbackException e) {
//***
throw e;
} catch (Throwable t) {
//***
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
if (!isCancelled) {
throw t;
}
throw t;
} finally {
//***
}
}
runWrapped() 是状态转换的关键方法,用于处理初始化——加载——解码:
- 判断当前状态
- 获取资源处理器
- 运行资源处理器
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
状态转换的关系在getNextStage() 方法中(跟磁盘缓存策略有关):
- RESOURCE_CACHE——缓存转换后的图片资源
- DATA_CACHE——只缓存原始的图片资源
- SOURCE——不缓存,只从网络加载
- FINISHED——只从缓存加载,状态变成结束;或者从网络加载的下一个状态也是结束
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
通过判断当前的状态,然后获取当前应该使用的数据获取生成器:
- RESOURCE_CACHE对应ResourceCacheGenerator()用于获取缓存的转换后的图片
- DATA_CACHE对应DataCacheGenerator()用户获取缓存的原始的图片资源
- SOURCE对应SourceGenerator()用于从网络加载图片
- 它们都持有了DecodeJob实现的FetcherReadyCallback接口,处理资源加载完成的回调
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
DecodeJob实现的FetcherReadyCallback回调:
@Override
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
}
看下RunReason的注释:
private enum RunReason {
/** The first time we've been submitted. */
INITIALIZE,
/** We want to switch from the disk cache service to the source executor. */
SWITCH_TO_SOURCE_SERVICE,
/**
* We retrieved some data on a thread we don't own and want to switch back to our thread to
* process the data.
*/
DECODE_DATA,
}
其中的SWITCH_TO_SOURCE_SERVICE表明是从磁盘缓存转换为数据处理。
其中的callback是EngineJob自己实现了DecodeJob.Callback接口,逻辑是再次执行DecodeJob:
@Override
public void reschedule(DecodeJob<?> job) {
// Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself
// up.
getActiveSourceExecutor().execute(job);
}
而DecodeJob的run()方法会继续调用runWrapped()方法,因为此时的runReason已变成SWITCH_TO_SOURCE,所以会继续调用runGenerators()方法。
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled
&& currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
可以看到runGenerators()是一个状态机的思路,一级一级往上获取图片资源,状态转换由getNextStage()实现,状态定义在Stage 中:
/** Where we're trying to decode data from. */
private enum Stage {
/** The initial stage. */
INITIALIZE,
/** Decode from a cached resource. */
RESOURCE_CACHE,
/** Decode from cached source data. */
DATA_CACHE,
/** Decode from retrieved source. */
SOURCE,
/** Encoding transformed resources after a successful load. */
ENCODE,
/** No more viable stages. */
FINISHED,
}
所以如果在RESOURCE_CACHE和DATA_CACHE的缓存中找到资源就结束,否则会进行网络请求。