在上一篇中,主要讲解了Glide 基础知识点以及with、load、into这三部曲中的with,知道了在with中Glide主要帮我们做了生命周期相互绑定的相关工作。在这一篇中,将会对load、into进一步解读相应的源码。
本篇解读的源码版本:4.11.0,读者也可以根据本章步骤,在AS中一步一步解读源码。
1、load 方法@NonNull @CheckResult @Override public RequestBuilderload(@Nullable String string) { return asDrawable().load(string); }
源码解析
这里有两个方法 asDrawable 和 load 现在分别进行源码解读。
1.1 asDrawable 方法@NonNull @CheckResult public RequestBuilderasDrawable() { return as(Drawable.class); }
源码解析
这里调用了as 方法,继续追进
@NonNull @CheckResult publicRequestBuilder as( @NonNull Class resourceClass) { return new RequestBuilder<>(glide, this, resourceClass, context); }
源码解析
到这,我们应该知道 asDrawable 方法最终 返回的是 RequestBuilder 对象,然后调用 load 方法。接下来就该分析 load方法是怎样走的。
1.2 load 方法@NonNull @Override @CheckResult public RequestBuilderload(@Nullable String string) { return loadGeneric(string); }
源码解析
这里调用了 loadGeneric 方法继续追进。
@NonNull private RequestBuilderloadGeneric(@Nullable Object model) { this.model = model; isModelSet = true; return this; }
源码解析
从这可以看出,loadGeneric 将对应参数(图片地址) 赋值给当前类的全局变量,最后再将该类返回。
1.3 图解总结这里虽然简单,但还是用一张图来总结一下,load的整个流程。
温馨提示:这里过程有点长,因为几乎所有的Glide逻辑都在这个方法里面。建议收藏关注一波,确保在足够多的空闲时间时再来捋一遍。
@NonNull public ViewTargetinto(@NonNull ImageView view) { Util.assertMainThread(); ...略 return into( glideContext.buildImageViewTarget(view, transcodeClass), null, requestOptions, Executors.mainThreadExecutor()); }
源码解析
这里首先进行了是否为主线程的处理,其次调用了 into 方法,进去看看。
private> Y into( @NonNull Y target, @Nullable RequestListener targetListener, baseRequestOptions> options, Executor callbackExecutor) { //构建 Request 对象 Request request = buildRequest(target, targetListener, options, callbackExecutor); Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { //这里是 请求失败重试判断,看是否重试 if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin(); } return target; } //这里是正常请求 requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }
源码解析
这里 先是进行了 Request 对象的构建,其次进行了 当前 Request 是否是新请求以及是否要重试,最后通过 requestManager.track 进行网络请求。先来分析一下 Request 对象的构建,进入buildRequest 方法。
2.1 开启 buildRequest 支线 private Request buildRequest(
Target target,
@Nullable RequestListener targetListener,
baseRequestOptions> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
new Object(),
target,
targetListener,
null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
源码解析
这里直接调用了 buildRequestRecursive 方法,进去看看。
private Request buildRequestRecursive(
Object requestLock,
Target target,
@Nullable RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
baseRequestOptions> requestOptions,
Executor callbackExecutor) {
...略
Request mainRequest =
buildThumbnailRequestRecursive(
requestLock,
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
Request errorRequest =
errorBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
源码解析
从这里可以看出,先是通过 buildThumbnailRequestRecursive 方法构建了 mainRequest 变量 ,如果没有失败请求(重试),那就直接返回。下面的也是处理因为失败的重试请求,最终也是返回了 Request 类型的变量。我们就不看重试的,直接进入 buildThumbnailRequestRecursive 方法。
private Request buildThumbnailRequestRecursive(
Object requestLock,
Target target,
RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
baseRequestOptions> requestOptions,
Executor callbackExecutor) {
...略
Request fullRequest =
obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator =
new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
Request fullRequest =
obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
baseRequestOptions> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(
requestLock,
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight,
callbackExecutor);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// base case: no thumbnail.
return obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
源码解析
从这可以看出,这里最多会有俩个请求 一个 fullRequest 正常状态的请求 ,thumbRequest 图标缩略图的请求。而正常请求 fullRequest 又是通过 obtainRequest 方法构建的,进去看看。
private Request obtainRequest(
Object requestLock,
Target target,
RequestListener targetListener,
baseRequestOptions> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
return SingleRequest.obtain(
context,
glideContext,
requestLock,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
源码解析
这里调用了 SingleRequest.obtain 方法,继续追进。
public staticSingleRequest obtain( Context context, GlideContext glideContext, Object requestLock, Object model, Class transcodeClass, baseRequestOptions> requestOptions, int overrideWidth, int overrideHeight, Priority priority, Target target, RequestListener targetListener, @Nullable List > requestListeners, RequestCoordinator requestCoordinator, Engine engine, TransitionFactory super R> animationFactory, Executor callbackExecutor) { return new SingleRequest<>( context, glideContext, requestLock, model, transcodeClass, requestOptions, overrideWidth, overrideHeight, priority, target, targetListener, requestListeners, requestCoordinator, engine, animationFactory, callbackExecutor); }
源码解析
这个方法返回了 SingleRequest 对象。到这,buildRequest 支线已经走完了。这里的 SingleRequest 对象,将会依次返回到主线,接下来回到主线看看。
2.2 结束 buildRequest 支线,回到主线。避免来回翻,这里再贴主线代码。
private> Y into( @NonNull Y target, @Nullable RequestListener targetListener, baseRequestOptions> options, Executor callbackExecutor) { //构建 Request 对象 Request request = buildRequest(target, targetListener, options, callbackExecutor); Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { //这里是 请求失败重试判断,看是否重试 if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin(); } return target; } //这里是正常请求 requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }
总结
到这,我们应该能明白 buildRequest 方法返回的 Request 对象,里面阔能会含有 缩略图 请求的封装。现在继续 看 requestManager.track 方法。
2.3 开启 requestManager.track 支线 synchronized void track(@NonNull Target> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
源码解析
这里分别调用了 targetTracker.track 和 requestTracker.runRequest 方法,依次进去看看。
- targetTracker.track
public void track(@NonNull Target> target) {
targets.add(target);
}
源码解析
这里我们可以理解为 将这个任务添加至某个集合里面。
- requestTracker.runRequest
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
源码解析
这里首先有两个集合,分别为:正在执行队列、暂停后等待执行队列。先是将该请求加入正在执行队列,然后判断当前Glide是否为暂停状态,如果否,则直接运行执行队列,如果是则清空正在执行队列,将当前请求加入等待执行队列。现在我们肯定是看执行的,于是进入begin方法看看。
如图所示
进入SingleRequest 里面的 begin 方法
@Override
public void begin() {
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
...略
//如果当前图片已经正在运行了,
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
// 如果当前状态为已完成状态,那么直接返回
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
//设置当前状态为等待状态
status = Status.WAITING_FOR_SIZE;
//进行宽高的判断,宽高是否大于0
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//满足进入该方法
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
...略
}
}
源码解析
从这可以看出,这里进行了一系列的逻辑判断,最终会进入 onSizeReady 方法。进入看看。
public final class SingleRequestimplements Request, SizeReadyCallback, ResourceCallback { ...略 @Override public void onSizeReady(int width, int height) { stateVerifier.throwIfRecycled(); synchronized (requestLock) { if (status != Status.WAITING_FOR_SIZE) { return; } status = Status.RUNNING; float sizeMultiplier = requestOptions.getSizeMultiplier(); this.width = maybeApplySizeMultiplier(width, sizeMultiplier); this.height = maybeApplySizeMultiplier(height, sizeMultiplier); loadStatus = engine.load( glideContext, model, requestOptions.getSignature(), this.width, this.height, requestOptions.getResourceClass(), transcodeClass, priority, requestOptions.getDiskCacheStrategy(), requestOptions.getTransformations(), requestOptions.isTransformationRequired(), requestOptions.isScaleOnlyOrNoTransform(), requestOptions.getOptions(), requestOptions.isMemoryCacheable(), requestOptions.getUseUnlimitedSourceGeneratorsPool(), requestOptions.getUseAnimationPool(), requestOptions.getOnlyRetrieveFromCache(), this, // SingleRequest implements Request, SizeReadyCallback, ResourceCallback callbackExecutor); if (status != Status.RUNNING) { loadStatus = null; } } } ...略 }
源码解析
从这可以看出,如果这里status 不等于上面设置的 等待状态,那么将直接终止。过后将对应的 status 设置为运行状态,随后根据比例进行了 宽高计算,最后调用了 engine.load 方法,并且传入了 当前对象 this ,而当前类实现了 Request, SizeReadyCallback, ResourceCallback 对应的接口,用来响应回调。我们进入engine.load 该方法看看。
publicLoadStatus load( GlideContext glideContext, Object model, Key signature, int width, int height, Class> resourceClass, Class transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map , Transformation>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, Options options, boolean isMemoryCacheable, boolean useUnlimitedSourceExecutorPool, boolean useAnimationPool, boolean onlyRetrieveFromCache, ResourceCallback cb, //具有回调功能 Executor callbackExecutor) { long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0; //根据对应的请求方式,生成对应请求的缓存key值 EngineKey key = keyFactory.buildKey( model, signature, width, height, transformations, resourceClass, transcodeClass, options); EngineResource> memoryResource; synchronized (this) { memoryResource = loadFromMemory(key, isMemoryCacheable, startTime); if (memoryResource == null) { return waitForExistingOrStartNewJob( glideContext, model, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, options, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache, cb,// 具有回调功能 callbackExecutor, key, startTime); } } //如果成功从缓存里面拿到对应数据了,那么调用onResourceReady方法将缓存数据返回给上一层。 cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE); return null; }
源码解析
这里首先根据相应的请求生成了对应的缓存key ,然后调用 loadFromMemory 方法查询是否有对应缓存,如果有则通过 cb.onResourceReady 方法将对应缓存数据返回给上一层;如果没有则调用 waitForExistingOrStartNewJob 方法。
我们先进入 loadFromMemory 方法看看
@Nullable
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;
}
源码解析
从这段代码可以看出,如果没开启缓存,返回null,如果没有活动缓存则读取内存缓存,如果其中一个有缓存则返回对应缓存,如果两个都没有则返回null。
接下来该进入 waitForExistingOrStartNewJob 方法看看。
privateLoadStatus waitForExistingOrStartNewJob( GlideContext glideContext, Object model, Key signature, int width, int height, Class> resourceClass, Class transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map , Transformation>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, Options options, boolean isMemoryCacheable, boolean useUnlimitedSourceExecutorPool, boolean useAnimationPool, boolean onlyRetrieveFromCache, ResourceCallback cb, // 具有回调功能 Executor callbackExecutor, EngineKey key, long startTime) { // 从工作队列中通过key 去寻找是否有 对应的 工作引擎 EngineJob> current = jobs.get(key, onlyRetrieveFromCache); if (current != null) { current.addCallback(cb, callbackExecutor); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Added to existing load", startTime, key); } return new LoadStatus(cb, current); } //如果没有则根据对应 key 创建对应的工作引擎 EngineJob engineJob = engineJobFactory.build( key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache); //创建对应的解码器 DecodeJob decodeJob = decodeJobFactory.build( glideContext, model, key, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, onlyRetrieveFromCache, options, engineJob); //将对应的工作引擎 添加至map中 jobs.put(key, engineJob); //向对应的工作引擎添加可回调的功能 engineJob.addCallback(cb, callbackExecutor); //开始工作,调用解码器 engineJob.start(decodeJob); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Started new load", startTime, key); } return new LoadStatus(cb, engineJob); }
源码解析
这里先是从对应的工作引擎Map查询是否存在已有引擎,如果没有则创建对应的工作引擎以及对应的解码器引擎,然后相互绑定对应的信息,最后调用engineJob.start方法开始工作。接下来进入该方法看看。
public synchronized void start(DecodeJobdecodeJob) { this.decodeJob = decodeJob; GlideExecutor executor = decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); executor.execute(decodeJob); }
源码解析
看到这样的代码 executor.execute 就能直接联想到 DecodeJob 这个类一定实现了 Runnable 接口以及核心逻辑也在对应的run方法里面,也是在这开启了线程(面试官最喜欢问的),接下来直接定位对应方法。
@Override
public void run() {
GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
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 {
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection();
}
}
源码解析
这里调用了 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 方法,传入的是 INITIALIZE,那么
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
//如果此请求应尝试解码缓存的资源数据,则返回 true。
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
//如果此请求应尝试解码缓存的源数据,则返回 true。
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);
}
}
源码解析
我们先假设不使用任何缓存,或者图片是第一次加载(缓存没数据),那么代码先进入 INITIALIZE,然后递归调用 参数为 Stage.RESOURCE_CACHE,最终会到 case DATA_CACHE ,接着进行 onlyRetrieveFromCache 判断,如果 这个为 true,该图片加载直接完成,否则就为 Stage.SOURCE
也就是说,如果,你的代码是这样写的。
final String url = "https://img1.baidu.com/it/u=4186787118,517350218&fm=26&fmt=auto&gp=0.jpg";
//除了生命周期,其他的功能都由into方法给干了
Glide.with(this).load(url)
.apply(RequestOptions.priorityOf(Priority.HIGH).onlyRetrieveFromCache(true))
.into(iv_image1);
那么你的图片,在没有本地缓存的情况下,永远加载不了图片!永远!Forever!
好了继续回到解读源码中
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 在正常情况下会返回 Stage.SOURCE ,那么进入 getNextGenerator 方法
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);
}
}
源码解析
这里的 stage 为 SOURCE 也就是说, 返回的是:SourceGenerator。继续回到上一层,接着调用了 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;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
源码解析
这里一看有个whlie循环,看最后一个条件判断,调用了currentGenerator.startNext(),进去看看。
如图所示
因为刚刚 得到的是 SourceGenerator,所以进入该类的这个方法。
@Override
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
//判断资源加载器是否为空,以及判断资源加载器加载的数据是否成功
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
//如果前面没有成功获取数据,那么后面将会尝试从缓存里面拿取数据。
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
startNextLoad(loadData);
}
}
return started;
}
源码解析
这里首先 调用了方法 cacheData 向 生成器 **sourceCacheGenerator ** 赋值,随后进行非空判断,最后 调用了方法 startNext,进去看看。
@Override
public boolean startNext() {
while (modelLoaders == null || !hasNextModelLoader()) {
...略
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
源码解析
这里我们可以看到 调用了 modelLoader.buildLoadData 方法返回的 loadData,所以继续进入该方法。
如图所示
进入该类,该方法。
@Override public LoadDatabuildLoadData( @NonNull GlideUrl model, int width, int height, @NonNull Options options) { GlideUrl url = model; if (modelCache != null) { url = modelCache.get(model, 0, 0); if (url == null) { modelCache.put(model, 0, 0, model); url = model; } } int timeout = options.get(TIMEOUT); return new LoadData<>(url, new HttpUrlFetcher(url, timeout)); }
源码解析
这里直接定位到最后一句,实例化了LoadData,里面构造参数又实例化了 HttpUrlFetcher 对象,直接定位到HttpUrlFetcher.loadData 方法。
@Override
public void loadData(
@NonNull Priority priority, @NonNull DataCallback super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException e) {
} finally {
}
}
源码解析
这里调用了 loadDataWithRedirects 方法拿到对应的流文件,进去看看这个方法怎么获取的。
private InputStream loadDataWithRedirects(
URL url, int redirects, URL lastUrl, Map headers) throws IOException {
...略
urlConnection = connectionFactory.build(url);
for (Map.Entry headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.connect();
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
//网络连接成功,并且code为正常的200
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
//处理重定向问题
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new HttpException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
cleanup();
//获取到了重定向地址,再次递归调用该方法
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
源码解析
解析到这,终于到连接网络这了,这里先是用HttpURLConnection 连接网络,连接成功后如果code为200则直接通过方法getStreamForSuccessfulRequest返回对应流,如果为重定向的code,那么解析对应重定向的地址,再次递归调用该方法。现在回到上一步,看看这个方法返回的网络流是怎么处理的。
@Override
public void loadData(
@NonNull Priority priority, @NonNull DataCallback super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException e) {
} finally {
}
}
源码解析
从这可以看出,这里调用了 callback.onDataReady 将流,返回给了上一层,接下来该去寻找实现这个方法的接收方了。
如图所示
因为我们是从DataCacheGenerator 进入的网络请求,那么返回也会到DataCacheGenerator这里面。
@Override
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}
源码解析
继续追进方法onDataFetcherReady,快完了。
如图所示
我们刚开始通过DecodeJob这个类一步一步进入的,那么返回也要是这个类。
@Override
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) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
源码解析
这里有一个是否主线程的判断,因为我们这个返回是从网络连接返回的,所以当前线程为子线程,就只能进else里面。在else里面调用了方法 decodeFromRetrievedData,进去看看。
private void decodeFromRetrievedData() {
Resource 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 方法,返回了 Resource 对象。因为等会要回到这里,处理下面的逻辑,所以再开一个支线。
2.3.1 开启 decodeFromData 支线private ResourcedecodeFromData( DataFetcher> fetcher, Data data, DataSource dataSource) throws GlideException { try { if (data == null) { return null; } long startTime = LogTime.getLogTime(); Resource result = decodeFromFetcher(data, dataSource); return result; } finally { fetcher.cleanup(); } }
源码解析
不想多说了,直接进入 decodeFromFetcher 方法。
private ResourcedecodeFromFetcher(Data data, DataSource dataSource) throws GlideException { LoadPath path = decodeHelper.getLoadPath((Class) data.getClass()); return runLoadPath(data, dataSource, path); }
源码解析
高情商:这嵌套的真好;低情商:这尼玛还没完。
这里调用了 runLoadPath 方法,追进。
private ResourcerunLoadPath( Data data, DataSource dataSource, LoadPath path) throws GlideException { Options options = getOptionsWithHardwareConfig(dataSource); DataRewinder rewinder = glideContext.getRegistry().getRewinder(data); try { return path.load( rewinder, options, width, height, new DecodeCallback (dataSource)); } finally { rewinder.cleanup(); } }
源码解析
继续进入 path.load,不信了,还能一直下去。
public Resourceload( DataRewinder rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback decodeCallback) throws GlideException { List throwables = Preconditions.checkNotNull(listPool.acquire()); try { return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables); } finally { listPool.release(throwables); } }
源码解析
继续追进 loadWithExceptionList 方法。
private ResourceloadWithExceptionList( DataRewinder rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback decodeCallback, List exceptions) throws GlideException { Resource result = null; for (int i = 0, size = decodePaths.size(); i < size; i++) { DecodePath path = decodePaths.get(i); try { result = path.decode(rewinder, width, height, options, decodeCallback); } catch (GlideException e) { exceptions.add(e); } if (result != null) { break; } } if (result == null) { throw new GlideException(failureMessage, new ArrayList<>(exceptions)); } return result; }
源码解析
哇,要蚌不住了,进入 path.decode 方法。
public Resourcedecode( DataRewinder rewinder, int width, int height, @NonNull Options options, DecodeCallback callback) throws GlideException { Resource decoded = decodeResource(rewinder, width, height, options); Resource transformed = callback.onResourceDecoded(decoded); return transcoder.transcode(transformed, options); }
源码解析
蚌不住了,进入 transcoder.transcode 看看。
如图所示
看上面注释 感觉快完了,这里我们随便选一个进去看看。
public class BitmapBytesTranscoder implements ResourceTranscoder{ ...略 @Nullable @Override public Resource transcode( @NonNull Resource toTranscode, @NonNull Options options) { ByteArrayOutputStream os = new ByteArrayOutputStream(); toTranscode.get().compress(compressFormat, quality, os); toTranscode.recycle(); return new BytesResource(os.toByteArray()); } ...略 }
源码解析
哈哈哈哈,终于给我找到了,看到没,将流转化为 Bitmap,然后释放,最后将转换好的资源依次返回。
这条支线终于走完了,继续回到2.3
2.3.2 结束 decodeFromData 支线 private void decodeFromRetrievedData() {
Resource 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 里面的逻辑,返回的resource是转化好了的图片资源 ,如果为空,则调用 刚刚我们分析过的方法 runGenerators ,如果不为空则调用 notifyEncodeAndRelease,进入该方法看看。
private void notifyEncodeAndRelease(Resourceresource, DataSource dataSource) { ...略 notifyComplete(result, dataSource); ...略 }
源码解析
进入该方法
private void notifyComplete(Resourceresource, DataSource dataSource) { setNotifiedOrThrow(); callback.onResourceReady(resource, dataSource); }
源码解析
在这终于调用了 callback.onResourceReady 这个回调了,感觉快要结束了,但是在这又要开启一条支线了。
2.3.3 开启 callback.onResourceReady 支线@Override public void onResourceReady(Resourceresource, DataSource dataSource) { synchronized (this) { this.resource = resource; this.dataSource = dataSource; } notifyCallbacksOfResult(); }
源码解析
继续追进 notifyCallbacksOfResult
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
resource.recycle();
release();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
} else if (hasResource) {
throw new IllegalStateException("Already have resource");
}
engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
engineJobListener.onEngineJobComplete(this, localKey, localResource);
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
源码解析
这里对资源进行了一系列处理,最后调用了 engineJobListener.onEngineJobComplete 方法
@Override
public synchronized void onEngineJobComplete(
EngineJob> engineJob, Key key, EngineResource> resource) {
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null && resource.isMemoryCacheable()) {
activeResources.activate(key, resource);
}
jobs.removeIfCurrent(key, engineJob);
}
源码解析
这里调用了 activeResources.activate 方法,继续追进
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();
}
}
源码解析
在这可以看出,这里向活动缓存队列里面添加了对应图片的缓存,到这条支线也走完了。
2.3.4 结束 callback.onResourceReady 支线现在回到最外层的 SingleRequest的onResourceReady
@Override
public void onResourceReady(Resource> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
Resource> toRelease = null;
try {
synchronized (requestLock) {
...略
onResourceReady((Resource) resource, (R) received, dataSource);
}
} finally {
if (toRelease != null) {
engine.release(toRelease);
}
}
}
源码解析
这里进行一系列的处理,最终会调用onResourceReady 方法。
private void onResourceReady(Resourceresource, R result, DataSource dataSource) { // We must call isFirstReadyResource before setting status. boolean isFirstResource = isFirstReadyResource(); status = Status.COMPLETE; this.resource = resource; isCallingCallbacks = true; try { boolean anyListenerHandledUpdatingTarget = false; ...略 if (!anyListenerHandledUpdatingTarget) { Transition super R> animation = animationFactory.build(dataSource, isFirstResource); target.onResourceReady(result, animation); } } finally { isCallingCallbacks = false; } notifyLoadSuccess(); }
源码解析
这里会调用 target.onResourceReady 这个方法。继续追进。
如图所示
因为这里是要给图片展示数据,这里就选择 ImageView 相关的。
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition super Z> transition) {
//判断是否有动画
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
//展示动画
maybeUpdateAnimatable(resource);
}
}
源码解析
这里有个是否存在动画的判断,没有就直接展示图片,所以直接定位到 方法 setResourceInternal。
private void setResourceInternal(@Nullable Z resource) {
// Order matters here. Set the resource first to make sure that the Drawable has a valid and
// non-null Callback before starting it.
setResource(resource);
maybeUpdateAnimatable(resource);
}
源码解析
这里依然进入setResource
如图所示
任选其一,随便进一个。
public class BitmapImageViewTarget extends ImageViewTarget{ ...略 @Override protected void setResource(Bitmap resource) { view.setImageBitmap(resource); } ...略 }
源码解析
哈哈哈哈哈哈哈哈哈,终于到达终点了!只想说!还有谁?一步一步分析进入,再一步一步回调出来。过程之艰辛。反正我坚持过来了,不知道读者有没有看到这里来。
2.4 图解总结 3、总结到这里,还是总结一下,Glide的三部曲:with、load、into 。
- with 具有生命周期相互绑定的功能
- load 具有待加载的图片资源赋值(比如网络图片Url,本地文件File等)
- into 具有图片处理的核心功能(图片加载、图片缓存等)
好了,相信看到这里,你应该对Glide源码有所了解了。在下一篇文章中,将会详细讲解Glide的缓存逻辑。



