本文共 8223 字,大约阅读时间需要 27 分钟。
当 Glide 从网络加载原始的数据的时候,会来到 HttpUrlFetcher#loadData()
方法,在 中说过,当加载完成后,会通过 callback.onDataReady()
方法将结果回传,最终会回溯到 DecodeJob#onDataFetcherReady
这个方法中,下面将会回溯的具体流程进行分析。
// HttpUrlFetcher.javapublic void loadData( @NonNull Priority priority, @NonNull DataCallback callback) { long startTime = LogTime.getLogTime(); try { // 获取网络图片, 内部使用了 HttpURLConnection 实现, 仅仅做了重定向的处理 InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders()); // 回调 callback.onDataReady() 方法将结果回传, // callback 是在调用方法时传递过来的,这里即 SourceGenerator#startNext() 方法中传递的,即 SourceGenerator 对象自身 callback.onDataReady(result); } catch (IOException e) { callback.onLoadFailed(e); } finally { ... }}
在 HttpUrlFetcher#loadData()
中得到加载的数据的 InputStream
之后,会将其传入回调方法进行处理。
其中 callback
是在调用方法时传递进来的。而方法是在 SourceGenerator#startNext()
进行调用的。
// SourceGenerator.javapublic boolean startNext() { ... sourceCacheGenerator = null; loadData = null; boolean started = false; while (!started && hasNextModelLoader()) { // 1. 从 DecodeHelper 的数据加载集合中, 获取一个数据加载器 loadData = helper.getLoadData().get(loadDataListIndex++); if (loadData != null && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource()) || helper.hasLoadPath(loadData.fetcher.getDataClass()))) { started = true; // 2. 使用加载器中 fetcher 执行数据加载 // 加载网络的 url 资源对应的就是 HttpGlideUrlLoader, // 它对应的 ModelLoader.LoadData 中的 fetcher 为 HttpUrlFetcher 类型 loadData.fetcher.loadData(helper.getPriority(), this); } } return started;}
可以看到看到传递的 callback
即为 SourceGenerator
对象自身(其实现了 DataCallback
接口)。
// SourceGenerator.javapublic void onDataReady(Object data) { ... if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) { // 将数据赋值给 dataToCache dataToCache = data; // We might be being called back on someone else's thread. Before doing anything, // we should reschedule to get back onto Glide's thread. // 数据加载回调 onDataReady() 是在子线程中,应该切换回 Glide 的线程。 // 进一步回调,cb 是在 new SourceGenerator 时传递过来的,为 DecodeJob 对象 cb.reschedule(); } else { ... }}// 注意 FetcherReadyCallback#reschedule() 的目的就是为了请求在 Glide 所属的线程// 中再次调用 DataFetcherGenerator#startNext() 方法,// DataFetcherGenerator 即为 SourceGenerator 的父类。interface FetcherReadyCallback { /** * Requests that we call startNext() again on a Glide owned thread. */ void reschedule(); ...}
SourceGenerator#cb
是在初始化的时候传递过来的。更具体的,是在 DecodeJob#getNextGenerator()
方法中创建时传递进来的。
// DecodeJob.javaprivate DataFetcherGenerator getNextGenerator() { switch (stage) { ... case SOURCE: // 对应加载的图片的 Generator return new SourceGenerator(decodeHelper, this); ... }}public void reschedule() { // 将 runReason 状态更新为 RunReason.SWITCH_TO_SOURCE_SERVICE runReason = RunReason.SWITCH_TO_SOURCE_SERVICE; // callback 则是在 `DecodeJob#init()` 时从外部传递进来的对应的 EngineJob 对象 callback.reschedule(this);}
可以看到 new SourceGenerator 时第二参数传递的是 DecodeJob 对象自身(其实现了 FetcherReadyCallback
接口)。
因此 SourceGenerator#onDataReady()
中执行 cb.reschedule()
实际上是执行 DecodeJob#reschedule()
。
然后又会进一步调用 callback.reschedule(this)
。callback
则是在 DecodeJob#init()
时从外部传递进来的,实际上为对应的 EngineJob 对象。
具体是在 Engine#load() 中,当内存缓存中没有获取到目标资源时,就会进一步从磁盘或者网络获取资源。此时就会构建 EngineJob 与 DecodeJob 对象。
因此在 DecodeJob#reschedule()
又会进一步回调 EngineJob#reschedule()
。
// EngineJob.javapublic void reschedule(DecodeJob job) { getActiveSourceExecutor().execute(job);}
getActiveSourceExecutor()
会获得对应的 GlideExecutor
,调用 GlideExecutor#execute()
实际上就是使用 GlideExecutor
内部的线程池来处理 Runnable
(DecodeJob
实现了 Runnable
接口)。
从而实现了前面(在 SourceGenerator#onDataReady()
方法中)说的从加载资源的子线程切换到 Glide 线程。
因此,此时又会执行 DecodeJob#run()
方法,进而执行 DecodeJob#runWrapped()
方法。
// DecodeJob.javaprivate 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); }}// 非静态内部类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,}
此时 runReason
已经变为 SWITCH_TO_SOURCE_SERVICE
了(在回调 DecodeJob#reschedule()
被赋值更新的)。
因此此时会在 GlideExecutor
对应的线程池中去执行 runGenerators()
,进而调用 currentGenerator.startNext()
。从而实现 FetcherReadyCallback#reschedule()
的目的,即切换回 Glide 线程再次调用 startNext()
。
又回到 SourceGenerator#startNext()
。
// SourceGenerator.javapublic boolean startNext() { if (dataToCache != null) { Object data = dataToCache; dataToCache = null; cacheData(data); } if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) { return true; } sourceCacheGenerator = null; ...}// 将数据缓存到磁盘中private void cacheData(Object dataToCache) { long startTime = LogTime.getLogTime(); try { // 这里的 encoder 实际上为 StreamEncoder(在 Glide 的构造方法中注册的,用于处理 InputStream 类型的数据的) Encoder
在前面的 SourceGenerator#onDataReady() 被回调的时候,会将加载的数据赋值给 dataToCache
,即 dataToCache
此时不为空,因此进入到 if 语句中。
在 cacheData()
方法中,会将加载的数据缓存到磁盘中,且会为 sourceCacheGenerator 赋值新的 DataCacheGenerator 对象。
因此对于后面的 if 语句,sourceCacheGenerator 不会为空。进入到 sourceCacheGenerator.startNext() 中,即 DataCacheGenerator#startNext()
中。
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) { return true;}
// DataCacheGenerator.javapublic boolean startNext() { ... loadData = null; boolean started = false; while (!started && hasNextModelLoader()) { ModelLoadermodelLoader = modelLoaders.get(modelLoaderIndex++); loadData = modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions()); if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) { started = true; // 这里的 fetcher 为 FileFetcher,调用其 loadData() 的时候又会把自身传递过去 loadData.fetcher.loadData(helper.getPriority(), this); } } return started;}
注意,在调用 FileFetcher#loadData() 的时候,会把 DataCacheGenerator 对象自身传递过去,因为其实现了 DataFetcher.DataCallback
接口。
// FileFetcher.javapublic void loadData(@NonNull Priority priority, @NonNull DataCallback callback) { try { data = opener.open(file); } catch (FileNotFoundException e) { callback.onLoadFailed(e); return; } callback.onDataReady(data);}
根据 File file
得到 data
,又会回调 DataCacheGenerator#onDataReady()
。
// DataCacheGenerator.javapublic void onDataReady(Object data) { cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);}
而成员变量 DataCacheGenerator#cb
则是通过 DataCacheGenerator
的构造方法传递进来的,具体是在 SourceGenerator#cacheData()
中传递的,实际上就是 SourceGenerator
对象自身。
// SourceGenerator.javapublic void onDataFetcherReady(Key sourceKey, Object data, DataFetcher fetcher, DataSource dataSource, Key attemptedKey) { // This data fetcher will be loading from a File and provide the wrong data source, so override // with the data source of the original fetcher cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);}
而 SourceGenerator#cb
在前面也说过,同样是在 new 的时候传递进来的,即 DecodeJob
对象,因此最终会回调搭到 DecodeJob#onDataFetcherReady()
。
注意,到目前为止,是在前面切换到 GlideExecutor
的线程池的线程中来执行的。
到这里,就是从 HttpUrlFetcher#loadData()
最终回溯到 DecodeJob#onDataFetcherReady()
的具体流程。
转载地址:http://brerj.baihongyu.com/