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/storage/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
中是怎样履行恳求的。