Glide 源码阅览笔记(三)
在榜首篇文章中我简略介绍了Glide实例的创立过程,要点介绍了Glide的内存缓存完结和磁盘的缓存完结:Glide 源码阅览笔记(一)
在第二篇文章中介绍了 Glide 对生命周期的办理: Glide 源码阅览笔记(二)
今日咱们持续今日的内容。
源码阅览基于Glide 4.16.0版本
Reqeust 和 RequestCoordinator
Request 比较好了解,它便是一个图片加载的使命。RequestCoordinator 它也是继承于 Request,它是用来和谐它内部的多个 Request,这么说比较抽象。我这儿简略举一个比如。咱们能够在运用 Glide 时,增加一个反常时恳求的使命,当主使命加载失利时 Glide 就会去加载这个反常时恳求的使命。例如以下代码:
val errorRequestBuilder = Glide.with(this)
.load("")
Glide.with(this)
.load("https://www.6hu.cc/wp-content/uploads/2024/01/230444-xgqIme.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240")
.error(errorRequestBuilder)
.into(findViewById<ImageView>(R.id.my_iv))
其间怎样和谐主 Request 与过错相关的 Request,便是 ErrorRequestCoordinator 的工作,它的工作原理十分简略,首先触发主 Request,当它恳求失利时再去加载反常的 Request。相似原理的还有 ThumbnailRequestCoordinator,它是和谐缩略图加载的 RequestCoordinator。后边的代码剖析中咱们都能看到他们。经过 RequestCoordinator 能够把单个 Request 构建成一个 Request 的恳求树,能够用这个恳求树来履行杂乱的恳求逻辑。
咱们在运用 Glide 构建完 RequestBuilder 后,会经过 into() 办法把终究的成果烘托到对应 ImageView (当然咱们也能够不烘托到 ImageView 中,这需求咱们自定义)。所以咱们也以 RequestBuilder#into() 办法作为今日剖析的入口函数:
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
// 校验必须在主线程
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
// 假如没有设置图片的裁剪办法,依据 ImageView 的 ScaleType 来核算。
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// Clone in this method so that if we use this RequestBuilder to load into a View and then
// into a different target, we don't retain the transformation applied based on the previous
// View's scale type.
// 核算裁剪办法
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(
// 将 ImageView 封装成 Target
glideContext.buildImageViewTarget(view, transcodeClass),
/* targetListener= */ null,
requestOptions,
// 回调线程设置成主线程
Executors.mainThreadExecutor());
}
简略阐明下上面的代码:
-
into()办法必须在主线程调用。 - 假如
RequestBuilder没有设置裁剪办法,需求经过ImageView#getScaleType()来核算,处理裁剪办法的类是Transformations,它被保存在options中,后边咱们会再看到它的呈现。 - 然后经过
GlideContext#buildImageViewTarget()将ImageView封装成ViewTarget目标,这儿要注意咱们的trascodeClass是Drawable,它表明ViewTarget终究能够处理烘托的目标格式,然后持续调用into()办法。
咱们去看看 GlideContext#buildImageViewTarget() 办法是怎样构建 ViewTarget 的:
@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
持续调用 ImageViewTargetFactory#buildTarget() 办法:
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(
@NonNull ImageView view, @NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
它所支撑的 transcodeClass 只能是 Bitmap 或许 Drawable,咱们的 demo 中是 Drawable,终究的 ViewTarget 完结类是 DrawableImageViewTarget()。
在看完了 ViewTarget 创立后,咱们持续咱们的主流程,持续看 into() 办法:
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
// 假如没有这是 model,直接报错。
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
// 构建 Request
Request request = buildRequest(target, targetListener, options, callbackExecutor);
// 获取前次的 Request
Request previous = target.getRequest();
// 假如前次的 Request 和 当时的恳求共同,直接开端前次的恳求
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
// 铲除 Target 中前次的恳求。
requestManager.clear(target);
// 将当时的 Request 设置到 Target 中。
target.setRequest(request);
// 将 target 和 request 告诉 RequestManager
requestManager.track(target, request);
return target;
}
简略阐明下上面的代码:
- 检查是否有设置
model,假如没有就直接报错,咱们设置的恳求url便是model。 - 经过
buildRequest()构建Request(后边要点剖析这个办法)。 - 判别
ViewTarget中前次的Request和当时的Request是否共同,假如共同,就直接回来当时办法(回来之前会判别一下前次的Request的运行状况,假如没有运行调用对应的begin()办法)。 - 经过
RequestManager#clear()办法铲除Target中的Request。 - 经过
Target#setRequest()办法将当时Request增加到Target中。 - 将
Target和Request告诉RequestManager。
咱们简略看看 ViewTarget#setRequest() 办法是怎样设置 Request 的:
@Override
public void setRequest(@Nullable Request request) {
setTag(request);
}
private void setTag(@Nullable Object tag) {
isTagUsedAtLeastOnce = true;
view.setTag(tagId, tag);
}
Request 其实便是被增加到 View 的 tag 上,对应的 tagId 是 R.id.glide_custom_view_target_tag。
咱们再看看 RequestManager#track() 办法是怎样处理 Target 和 Request 的:
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
这儿 target 交由 TargetTracker 处理;request 交由 RequestTracker 来处理。
public void track(@NonNull Target<?> target) {
targets.add(target);
}
TargetTracker 处理十分简略,直接增加到列表中。
再看看 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);
}
}
将 request 增加到 requests 列表中,假如当时没有暂停(也便是 onStart() 生命周期)调用 Request#begin() 办法;假如当时已经被暂停,会调用 Request#clear() 办法,然后增加到 pendingRequests 列表中。
咱们持续看看 RequestBuilder#into() 办法中调用过的 buildeRequest() 办法(期望你还没有忘掉),看看它是怎样构建 Request 的。
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) {
// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
ErrorRequestCoordinator errorRequestCoordinator = null;
// 假如有 ErrorBuilder,构建一个 ErrorRequestCoordinator,一起它作为 parentCoordinator
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
// 构建 MainRequest
Request mainRequest =
buildThumbnailRequestRecursive(
requestLock,
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
if (errorRequestCoordinator == null) {
// 假如没有对 Error 的处理,直接回来 mainRequest
return mainRequest;
}
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
// 经过 errorBuilder 构建 errorRequest。
Request errorRequest =
errorBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
// 将 mainRequest 和 errorRequest 增加到 ErrorRequestCoordinator 中
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
简略阐明下上面的办法:
- 假如有
errorBuilder,构建一个ErrorRequestCoordinator,一起它也是后续恳求的parent。 - 经过
buildThumbnailRequestRecursive()构建mainRequest。假如没有errorBuilder,直接把mainRequest作为成果回来办法。 - 经过
errorBuilder构建errorRequest。 - 将
mainRequest和errorRequest增加到ErrorRequestCoordinator中,然后把它作为成果回来。
咱们持续看看 buildThumbnailRequestRecursive() 办法是怎样 mainRequest 的。
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) {
// 判别是否有 thumbnailBuilder
if (thumbnailBuilder != null) {
if (isThumbnailBuilt) {
throw new IllegalStateException(
"You cannot use a request as both the main request and a "
+ "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
}
TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority =
thumbnailBuilder.isPrioritySet()
? thumbnailBuilder.getPriority()
: getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
// 创立一个 ThumbnailRequestCoordinator 目标
ThumbnailRequestCoordinator coordinator =
new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
// 构建 fullRequest,这其实便是咱们的主恳求
Request fullRequest =
obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// 构建 thumbRequest。
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
// 将 fullRequest 和 thumbRequest 增加到 ThumbnailRequestCoordinator 中
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// ...
return coordinator;
} else {
// 没有 thumbnailBuilder,直接构建一个 SingleRequest
return obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
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);
}
上面的代码看似许多,其实十分简略:
- 判别是否有
thumbnailBuilder(也便是缩略图),假如没有,直接构建一个SingleRequest回来,真实的恳求完结都是SingleRequest兑现。 - 构建一个
ThumbnailRequestCoordinator目标,它会作为后续恳求的parent。 - 构建主恳求
fullRequest和缩略图恳求thumbRequest,并把他们增加到ThumbnailRequestCoordinator中,然后将它作为成果回来。
所以到这儿咱们能够做一个恳求构建的总结了,咱们以最杂乱的状况为比如来阐明,也便是一起有 ErrorRequest 和 ThumbnailReqeust 的恳求:
首先构建一个 ErrorRequestCoordinator,然后经过 errorRequestBuilder 构建一个 errorRequest,持续构建一个 thumbnailRequest。他们都会被增加到 ErrorRequestCoordinator 中,他们的 parent 也都是 ErrorRequestCoordinator。
构建 thumnailRequest 时,先创立一个 ThumbnailRequestCoordinator,然后构建一个 fullRequest,也便是主恳求,然后构建一个 thumbnailRequest,也便是缩略图恳求。他们也都被增加到 ThumbnailRequestCoordinator 中,parent 也都是它。
ErrorRequestCoordinator
咱们先简略看看 ErrorRequestCoordinator#begin() 办法的完结:
@Override
public void begin() {
synchronized (requestLock) {
if (primaryState != RequestState.RUNNING) {
primaryState = RequestState.RUNNING;
primary.begin();
}
}
}
直接触发主恳求的 Request#begin()。
咱们持续看看 ErrorRequestCoordinator#onRequestFailed() 办法中是怎样处理失利恳求的:
@Override
public void onRequestFailed(Request request) {
synchronized (requestLock) {
// 假如当时失利的恳求不是 errorRequest,也便是表明主恳求失利了
if (!request.equals(error)) {
// 触发 error#begin() 办法
primaryState = RequestState.FAILED;
if (errorState != RequestState.RUNNING) {
errorState = RequestState.RUNNING;
error.begin();
}
return;
}
// 以下的状况表明主恳求和失利恳求都失利了
errorState = RequestState.FAILED;
if (parent != null) {
// 告诉 parent 恳求失利了
parent.onRequestFailed(this);
}
}
}
假如主恳求失利,就会触发 error 恳求开端;假如主恳求和过错的恳求都失利,就表明当时恳求失利了,然后它会告诉 parent。
ThumbnailRequestCoordinator
@Override
public void begin() {
synchronized (requestLock) {
isRunningDuringBegin = true;
try {
// 假如 full 恳求没有完结,一起 thumb 也没有在恳求中,触发 thumb 恳求。
if (fullState != RequestState.SUCCESS && thumbState != RequestState.RUNNING) {
thumbState = RequestState.RUNNING;
thumb.begin();
}
// 假如 full 没有在恳求中,触发 full 的恳求。
if (isRunningDuringBegin && fullState != RequestState.RUNNING) {
fullState = RequestState.RUNNING;
full.begin();
}
} finally {
isRunningDuringBegin = false;
}
}
}
假如 full 恳求没有完结,一起 thumb 也没有在恳求中,触发 thumb 恳求;假如 full 没有在恳求中,触发 full 的恳求。也便是它会一起触发 full 和 thumb 的恳求。
咱们持续看看 onRequestSuccess() 办法是怎样处理恳求成功的使命的:
@Override
public void onRequestSuccess(Request request) {
synchronized (requestLock) {
if (request.equals(thumb)) {
thumbState = RequestState.SUCCESS;
return;
}
fullState = RequestState.SUCCESS;
if (parent != null) {
parent.onRequestSuccess(this);
}
if (!thumbState.isComplete()) {
thumb.clear();
}
}
}
假如是 thumb 恳求成功,仅仅简略更新状况,然后回来;假如是 full 恳求成功,会告诉 parent,然后把 thumb 的恳求取消掉。
咱们再看看它是怎样处理恳求失利的使命的:
@Override
public void onRequestFailed(Request request) {
synchronized (requestLock) {
if (!request.equals(full)) {
thumbState = RequestState.FAILED;
return;
}
fullState = RequestState.FAILED;
if (parent != null) {
parent.onRequestFailed(this);
}
}
}
也是朴实无华的代码,当 thumb 恳求失利了,也是简略更新状况;full 恳求失利了,更新
状况,一起告诉 parent。
简略介绍 Registry
Registry 中注册了许多的重要的功用组件,它是经过 RegistryFactory 来创立实例和初始化的:
@Synthetic
static Registry createAndInitRegistry(
Glide glide,
List<GlideModule> manifestModules,
@Nullable AppGlideModule annotationGeneratedModule) {
BitmapPool bitmapPool = glide.getBitmapPool();
ArrayPool arrayPool = glide.getArrayPool();
Context context = glide.getGlideContext().getApplicationContext();
GlideExperiments experiments = glide.getGlideContext().getExperiments();
Registry registry = new Registry();
// 注册默许的体系组件
initializeDefaults(context, registry, bitmapPool, arrayPool, experiments);
// 注册自定义的组件,或许替换默许的体系组件
initializeModules(context, glide, registry, manifestModules, annotationGeneratedModule);
return registry;
}
经过 initializeDefaults() 来注册体系组件,等咱们后续需求时再来检查这个办法;经过 initializeModules() 来增加默许的组件,咱们先来看看它的完结:
private static void initializeModules(
Context context,
Glide glide,
Registry registry,
List<GlideModule> manifestModules,
@Nullable AppGlideModule annotationGeneratedModule) {
for (GlideModule module : manifestModules) {
try {
module.registerComponents(context, glide, registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: "
+ module.getClass().getName(),
e);
}
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(context, glide, registry);
}
}
不知道你是否还记得咱们是怎样把本来的网络恳求替换成 OkHttp 的?便是要经过上面办法触发咱们自定义的 AppGlideModule 的 registerComponents() 办法,经过这个办法咱们就能够替换原有的网络恳求为 OkHttp。
看到这儿你或许还是不太清楚 Registry 中详细注册了什么样功用的组件。我这儿以一次简略的网络恳求使命来描绘一下其间会用到哪些组件:
首先咱们输入的 url 是一个 String 目标,在 Glide 内部中被称为 model (它也能够是 File 类型,Drawable 类型等等),首先就需求 ModelLoader 来转换处理 model。所以 ModelLoader 就有一个输入类型和输出类型,首先要找到一个 ModelLoader 将 String 类型的 model 转换成 Url;然后持续找到一个 ModelLoader 将 Url 类型的 model 转换成 GlideUrl;终究找到将 GlideUrl 转换成 InputStream 类型的 ModelLoader,没错这个 ModelLoader 其实也便是履行的网络恳求,它也是处理的终究一个 ModelLoader,终究的处理成果就需求交由下一站的组件来处理。
这也是为什么替换原有的网络恳求为 OkHttp,的代码是下面这样:
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
super.registerComponents(context, glide, registry)
registry.replace(
GlideUrl::class.java,
InputStream::class.java,
OkHttpUrlLoader.Factory(appOkHttpClient)
)
}
ModelLoader 处理的下一站便是 Decoder,咱们的 ModelLoader 的输出类型是 InputStream,咱们就需求找到一个 Decoder 支撑的输入类型是 InputStream的,把 InputStream 解码成 Bitmap。
在到下一站便是 Transcoder,同样的它也是有一个输入类型和输出类型,Decoder 传过来的类型是 Bitmap,咱们需求将它处理成 ViewTarget 需求的 Drawable 类型,然后 ImageView 就能够直接烘托 Drawable 了。
我仅仅简略介绍了 Registry 中的 ModelLoader、Decoder 和 Transcoder 组件,他们是十分中心的组件。其间还有一些别的组件,比如在缓存到文件时就需求将 Bitmap 从头编码,这时就需求 Encoder。
终究
本篇文件介绍了 Reqeust 和 RequestCoordinator,还简略介绍了 Registry 中的中心组件(但是没有看源码)。由于本篇文章的篇幅也不短了,为了不像榜首篇文章那样过长,所以后续的文章持续讲 SingleRequest 中是怎样履行恳求的。
