上一篇,我们分析了with方法,文章链接:
https://blog.csdn.net/qq_36391075/article/details/82833260
在with方法中,进行了Glide的初始化,创建了RequesManger,并且绑定了生命周期,最终返回了一个RequestManager,现在,我们就来分析分析load
方法:
同样load
方法也有很多重载方法:
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
return asDrawable().load(drawable);
}
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
public RequestBuilder<Drawable> load(@Nullable File file) {
return asDrawable().load(file);
}
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return asDrawable().load(resourceId);
}
public RequestBuilder<Drawable> load(@Nullable URL url) {
return asDrawable().load(url);
}
public RequestBuilder<Drawable> load(@Nullable byte[] model) {
return asDrawable().load(model);
}
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
上面这些是它的所有的重载,我们可以看到,无论是哪个重载方法,都会先调用asDrawable()
,所以看看吧:
/**
* Attempts to always load the resource using any registered {@link
* com.bumptech.glide.load.ResourceDecoder}s that can decode any subclass of {@link Drawable}.
*尝试使用使用任何已经注册的了可以解码Drawable机及其子类的ResourceDecoder如加载资源
*
*
* <p> By default, may return either a {@link android.graphics.drawable.BitmapDrawable} or {@link
* GifDrawable}, but if additional decoders are registered for other {@link Drawable} subclasses,
* any of those subclasses may also be returned. </p>
*
* @return A new request builder for loading a {@link Drawable}.
*/
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
/**
* Attempts to load the resource using any registered
* {@link com.bumptech.glide.load.ResourceDecoder}s
* that can decode the given resource class or any subclass of the given resource class.
*
* @param resourceClass The resource to decode.
* @return A new request builder for loading the given resource class.
*/
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
我们可以看到asDrawable
方法最终返回了一个RequestBuilder对象,RequestBuilder是什么呢?
public class RequestBuilder<TranscodeType> implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>>
还是先看官网描述:
A generic class that can handle setting options and staring loads
for generic resource types.
@param <TranscodeType> The type of resource that will be delivered to the
{
@link com.bumptech.glide.request.target.Target}.
ReqestBuilder是一个通用类,可以处理设置的选项和启动加载通用resource类型。
它的构造方法:
protected RequestBuilder(Glide glide, RequestManager requestManager,
Class<TranscodeType> transcodeClass, Context context) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.requestOptions = defaultRequestOptions;
this.glideContext = glide.getGlideContext();
}
回到load
方法,调用asDrawable
方法得到RequestBuilder后,调用了RequestBuilder.load
方法:
RequestBuilder中也有一堆load
重载方法:
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable byte[] model) {
RequestBuilder<TranscodeType> result = loadGeneric(model);
if (!result.requestOptions.isDiskCacheStrategySet()) {
result = result.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
if (!result.requestOptions.isSkipMemoryCacheSet()) {
result = result.apply(skipMemoryCacheOf(true /*skipMemoryCache*/));
}
return result;
}
public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
return loadGeneric(drawable)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable File file) {
return loadGeneric(file);
}
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
}
public RequestBuilder<TranscodeType> load(@Nullable Object model) {
return loadGeneric(model);
}
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
return loadGeneric(uri);
}
上面就是它的所有的重载方法了,同样,都先调用了loadGeneric()
方法:
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
这个方法中只是简单的进行赋值操作,此处的model就是我们请求地址的String串。
load
方法就这样完了,我们接着往下看:
into方法
同样的,into
方法也有很多重载:
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
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(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null);
}
@NonNull
@Synthetic <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener) {
return into(target, targetListener, getMutableOptions());
}
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
但是我们可以看到,最后都调用了最后一个into
方法,对于我们比较收悉的第一个into,会保证ImageView的ScaleType到requestOptions。
现在我们就一起看看最后有个into
方法:
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
//构建Request对象
Request request = buildRequest(target, targetListener, options);
//得到之前的Request
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)//如果target的Request与当前新构建的Request相同,则重用
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
//否则,就将新苟安的request设置给target,同时由requestManager负责监督request的执行过程
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
上面代码,总的来说就是,先构建Request,如果新的Request和老的Request相同,就重用,否则就重新执行
于是,我们就先看看Request的构建过程吧:
首先我们还是先看看这个Request是什么鬼:
/**
* A request that loads a resource for an {@link com.bumptech.glide.request.target.Target}.
*/
public interface Request {
/**
* Starts an asynchronous load.
*/
void begin();
/**
* Identical to {@link #clear()} except that the request may later be restarted.
*/
void pause();
/**
* Prevents any bitmaps being loaded from previous requests, releases any resources held by this
* request, displays the current placeholder if one was provided, and marks the request as having
* been cancelled.
*/
void clear();
/**
* Returns true if this request is paused and may be restarted.
*/
boolean isPaused();
/**
* Returns true if this request is running and has not completed or failed.
*/
boolean isRunning();
/**
* Returns true if the request has completed successfully.
*/
boolean isComplete();
/**
* Returns true if a non-placeholder resource is put. For Requests that load more than one
* resource, isResourceSet may return true even if {@link #isComplete()}} returns false.
*/
boolean isResourceSet();
/**
* Returns true if the request has been cancelled.
*/
boolean isCancelled();
/**
* Returns true if the request has failed.
*/
boolean isFailed();
/**
* Recycles the request object and releases its resources.
*/
void recycle();
/**
* Returns {@code true} if this {@link Request} is equivalent to the given {@link Request} (has
* all of the same options and sizes).
*
* <p>This method is identical to {@link Object#equals(Object)} except that it's specific to
* {@link Request} subclasses. We do not use {@link Object#equals(Object)} directly because we
* track {@link Request}s in collections like {@link java.util.Set} and it's perfectly legitimate
* to have two different {@link Request} objects for two different
* {@link com.bumptech.glide.request.target.Target}s (for example). Using a similar but different
* method let's us selectively compare {@link Request} objects to each other when it's useful in
* specific scenarios.
*/
boolean isEquivalentTo(Request other);
}
我们可以看到,Request只是一个接口,根据里面的方法,我们可以猜到它相当于图片加载时的控制回调接口:
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions);
}
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
ErrorRequestCoordinator errorRequestCoordinator = null;
//v4支持error方法设置requestBuilder,也就是此处的errorBuilder
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions);
//如果没有设置erroBuilder,则直接返回这个正常的请求
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
//如果使用了,override方法重写了请求的图片的宽度和高度
//则需要将其设置给errorBuilder用于构建errorRequest
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.requestOptions.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
//如果设置了erroeBuilder,则构建一个errorRequest
Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
//ErrorRequestCoordinator:此类的作用就是如果mainRequest执行失败,则执行errorRequest
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
如果我们设置一个error(RequestBuilder),那么执行的流程就会是,先执行mainRequest,如果mainRequest执行失败,则执行errorRequest。
我们先看mainRequest的构建:
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
//如果我们设置了thumbnail(RequestBuilder)
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
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;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.requestOptions.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overr