DecodeJob实现了DataFetcherGenerator.FetcherReadyCallback接口:
interface FetcherReadyCallback {
//Glide重新调度,在Glide自己的线程中继续流程
void reschedule();
//数据获取成功
void onDataFetcherReady(
Key sourceKey,
@Nullable Object data,
DataFetcher<?> fetcher,
DataSource dataSource,
Key attemptedKey);
//数据获取失败
void onDataFetcherFailed(
Key attemptedKey, Exception e, DataFetcher<?> fetcher, DataSource dataSource);
}
onDataFetcherFailed数据获取失败的处理逻辑:
public void onDataFetcherFailed(
Key attemptedKey, Exception e, DataFetcher<?> fetcher, DataSource dataSource) {
fetcher.cleanup();
GlideException exception = new GlideException("Fetching data failed", e);
exception.setLoggingDetails(attemptedKey, dataSource, fetcher.getDataClass());
throwables.add(exception);
//线程不一样,修改runReason,重新调度,最终调用的还是runGenerators()
if (Thread.currentThread() != currentThread) {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
} else {
runGenerators();
}
}
因此,如果数据获取失败,会继续调用runGenerators(),逻辑如下:
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled
&& currentGenerator != null
//当前的generator开始加载数据
&& !(isStarted = currentGenerator.startNext())) {
//下一个状态
stage = getNextStage(stage);
//根据状态,获取数据加载器
currentGenerator = getNextGenerator();
//重新调度,切换到Glide自己的线程
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
-
继续调用当前的DataFetcherGenerator.startNext(),因为ResourceCacheGenerator和DataCacheGenerator中都有序号计数,之前已尝试的ModelLoader.LoadData不会重复调用,没有找到合适的ModelLoader.LoadData,就会返回false
-
调用getNextStage()获取下一个状态:
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: // Skip loading from source if the user opted to only retrieve the resource from cache. return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; case SOURCE: case FINISHED: return Stage.FINISHED; default: throw new IllegalArgumentException("Unrecognized stage: " + current); } }
-
如果RESOURCE_CACHE和DATA_CACHE都没找到,则会调用SourceGenerator
-
如果SOURCE也没有,那么请求失败,并且通知出去,notifyFailed()
reschedule重新调度:
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
}
重新调度只会发生在加载数据的阶段,所以设置runReason为RunReason.SWITCH_TO_SOURCE_SERVICE,并且调用callback的reschedule方法,而这个callback是EngineJob实现的(DecodeJob的创建逻辑在Engine中,且用到了对象池Pools.Pool)。
EngineJob的reschedule方法:
public void reschedule(DecodeJob<?> job) {
getActiveSourceExecutor().execute(job);
}
所以还是把DecodeJob丢到线程池里再次执行,最后还是调用了DecodeJob的run方法,判断状态后,调用了runWrapped方法。因为runReason的值,所以最终还是调用了runGenerators方法,用来加载数据。
onDataFetcherReady数据加载成功:
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
//变量保存
this.currentSourceKey = sourceKey;
this.currentData = data;
this.currentFetcher = fetcher;
this.currentDataSource = dataSource;
this.currentAttemptingKey = attemptedKey;
if (Thread.currentThread() != currentThread) {
//重新放到线程池里执行,执行run->runWrapped->decodeFromRetrievedData
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
不管是reschedule重新调度,还是直接处理,最终都是调用了decodeFromRetrievedData方法进行解码工作:
private void decodeFromRetrievedData() {
Resource<R> resource = null;
try {
//解码
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
//解码失败,重新加载数据,流程在上文已分析
runGenerators();
}
}
decodeFromData数据解码:
private <Data> Resource<R> decodeFromData(
DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
//根据数据类型获取解码器,如HttpUrlFetcher的结果是InputStream
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
return runLoadPath(data, dataSource, path);
}
private <Data, ResourceType> Resource<R> runLoadPath(
Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path)
throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
可以看到解码的工作最终交给了LoadPath来做,解码的结果通过DecodeCallback这个内部类的回调,把结果设置给了dataSource这边变量,并最终调用了DecodeJob的onResourceDecoded方法。
解码完成1
<Z> Resource<Z> onResourceDecoded(DataSource dataSource, @NonNull Resource<Z> decoded) {
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
//如果不是已转换的数据缓存,则先使用设置的Transformation
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
//直接回收数据节省内存,或者放到缓存中供下次使用
if (!decoded.equals(transformed)) {
decoded.recycle();
}
final EncodeStrategy encodeStrategy;
final ResourceEncoder<Z> encoder;
if (decodeHelper.isResourceEncoderAvailable(transformed)) {
encoder = decodeHelper.getResultEncoder(transformed);
encodeStrategy = encoder.getEncodeStrategy(options);
} else {
encoder = null;
encodeStrategy = EncodeStrategy.NONE;
}
Resource<Z> result = transformed;
boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
//缓存已转换的数据,因为此时的数据已解码,所以缓存到文件中,需要再次编码
if (diskCacheStrategy.isResourceCacheable(
isFromAlternateCacheKey, dataSource, encodeStrategy)) {
if (encoder == null) {
throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
}
final Key key;
switch (encodeStrategy) {
//Gif,定义在GifDrawableEncoder中
case SOURCE:
key = new DataCacheKey(currentSourceKey, signature);
break;
case TRANSFORMED:
//Bitmap,定义在BitmapEncoder中
key =
new ResourceCacheKey(
decodeHelper.getArrayPool(),
currentSourceKey,
signature,
width,
height,
appliedTransformation,
resourceSubClass,
options);
break;
default:
throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
}
//参数保存到deferredEncodeManager中,在下一步中进行encode
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
}
return result;
}
可以看到解码完成后,主要进行使用Transformation,并且转换的结果进行缓存。(感觉此处的处理会有重复,比如数据本身就是加载了已转换过的数据,此处又要进行编码和缓存到文件)
解码完成2
上述工作完成后会调用notifyEncodeAndRelease:
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
//因为解码工作是同步的,所以onResourceDecoded中会设置deferredEncodeManager
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
//将结果分发出去
notifyComplete(result, dataSource);
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
//将已转码的数据再编码并且缓存到文件中,主要工作在DiskLruCacheWrapper中
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
//事情都做完了,进行资源回收,并将变量置空,提升gc效率
onEncodeComplete();
}