前言
在上一篇中,主要讲解了Glide 基础知识点以及with、load、into这三部曲中的with,知道了在with中Glide主要帮我们做了生命周期相互绑定的相关工作。在这一篇中,将会对load、into进一步解读相应的源码。
Android开发Glide原理解析/面试题解析_哔哩哔哩_bilibili
本篇解读的源码版本:4.11.0,读者也可以根据本章步骤,在AS中一步一步解读源码。
1、load 方法
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
源码解析
这里有两个方法 asDrawable 和 load 现在分别进行源码解读。
1.1 asDrawable 方法
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
源码解析
这里调用了as 方法,继续追进
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
源码解析
到这,我们应该知道 asDrawable 方法最终 返回的是 RequestBuilder 对象,然后调用 load 方法。接下来就该分析 load方法是怎样走的。
1.2 load 方法
@NonNull
@Override
@CheckResult
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
源码解析
这里调用了 loadGeneric 方法继续追进。
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
源码解析
从这可以看出,loadGeneric 将对应参数(图片地址) 赋值给当前类的全局变量,最后再将该类返回。
1.3 图解总结
这里虽然简单,但还是用一张图来总结一下,load的整个流程。
2、into 方法
温馨提示:这里过程有点长,因为几乎所有的Glide逻辑都在这个方法里面。建议收藏关注一波,确保在足够多的空闲时间时再来捋一遍。
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
...略
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
源码解析
这里首先进行了是否为主线程的处理,其次调用了 into 方法,进去看看。
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> 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<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
/*requestLock=*/ new Object(),
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
源码解析
这里直接调用了 buildRequestRecursive 方法,进去看看。
private Request buildRequestRecursive(
Object requestLock,
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> 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<TranscodeType> target,
RequestListener<TranscodeType> 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<TranscodeType> target,
RequestListener<TranscodeType> 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 static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object requestLock,
Object model,
Class<R> transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> 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 extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> 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
/** Starts tracking the given request. */
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 SingleRequest<R> implements 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 该方法看看。
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, 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 方法看看。
private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, 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<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//创建对应的解码器
DecodeJob<R> 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);
}