Glide框架解析(2)

return retriever.get(activity);
}

public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}

public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}

无论调用的是哪个with重载方法,最后都会到这里: get(Activity activity)

// 无论调用的是哪个with重载方法,最后都会到这里
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
// 主要逻辑
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null);
}
}

主要逻辑

// 主要逻辑
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null);

进入**fragmentGet()**方法

// 这里新建了一个没有视图的RequestManagerFragment
private RequestManager fragmentGet(Context context,
android.app.FragmentManager fm,
android.app.Fragment parentHint) {
// 在这里我们创建了一个RequestManagerFragment对象,很明显这是一个Fragment。
// 而对于Fragment我们知道,它是可以和Activity的生命周期绑定到一起的;
// 而Fragment有两种表现形式,一种是有界面的Fragment,
// 一种是无界面的Fragment。而在这里这个RequestManagerFragment就是一个无界面的Fragment。
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);

RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
// 绑定requestManager和Fragment的Lifecycle
requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
// 这句话就将RequestManagerFragment与RequestManager绑定到一起(它们是一对一绑定的关系)。
// 因此,RequestManager的另一个重要作用就是:监听加载图片界面(Activity、Fragment)的生命周期。
current.setRequestManager(requestManager);
}
return requestManager;
}

RequestManagerFragment.class中持有一个lifecycle,在Fragment进入关键生命周期时会主动通知lifecycle执行相关方法

public class RequestManagerFragment extends Fragment {

private final ActivityFragmentLifecycle lifecycle;

@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}

@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}

@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
} 
}

ActivityFragmentLifecycle.class中持有一个lifecycleListeners,在Fragment进入关键生命周期时Lifecycle会通知他的所有Listener

class ActivityFragmentLifecycle implements Lifecycle {

private final Set lifecycleListeners;void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}

void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}

void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}

}

RequestManger.class关键生命周期中处理加载任务

@Override
public void onStart() {
resumeRequests();
targetTracker.onStart();
}

@Override
public void onStop() {
pauseRequests();
targetTracker.onStop();
}

@Override
public void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
}

1.3、总结
  1. Glide在加载绑定了Activity的生命周期。
  2. 在Activity内新建一个无UI的Fragment,这个特殊的Fragment持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。
  3. 在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。
1.4、面试

Glide为什么不能在子线程中with?

子线程中不会去添加 生命周期管理机制,主线程才会添加一个 空白的Fragment去监听 Activity Fragment的变化。

每一个with()方法重载的代码都非常简单,都是调用调用getRetriever(activity).get(activity),返回一个RequestManager对象。

getRetriever(…).get(…)做了什么事情?

不论传入Activity、FragmentActivity、Fragment最终都会调用supportFragmentGet()方法,而这两个方法最终流程都是一致的就是那就是会向当前的Activity当中添加一个隐藏的Fragment。

那么这里为什么要添加一个隐藏的Fragment呢?

答:因为Glide需要知道加载的生命周期。很简单的一个道理,如果你在某个Activity上正在加载着一张图片,结果图片还没加载出来,这时候Activity被用户关掉了,那么图片就应该取消加载,可是Glide并不知道Activity的生命周期,怎么办呢? 于是Glide就使用了添加隐藏Fragment的这种小技巧,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了。

既然有了Application,为什么不用registerActivityLifecycleCallbacks而是用隐藏的Fragment?

registerActivityLifecycleCallbacks是可以实现,并且我的小伙伴在自己的某些工程中也在使用,但是个人理解是这样的: registerActivityLifecycleCallbacks监控所有的Activity生命周期,然而当你使用Glide加载图片时,并不是所有的Activity都会用到Glide加载图片(大多数情况),所以呢,使用registerActivityLifecycleCallbacks存在资源浪费的现象。不仅如此,你监控了所有的activity怎么和Glide想要监控的Activity关联到一块去,虽然可以实现,但是这个办法真心不实用,既然Glide给了我们这么完美的解决方案我们就要学以致用,以后尽力用到自己的工程中去。

2、load()
2.2、源码

由于with()方法返回的是一个RequestManager对象,那么很容易就能想到,load()方法是在RequestManager类当中的,所以说我们首先要看的就是RequestManager这个类。不过在上一篇文章中我们学过,Glide是支持图片URL字符串、图片本地路径等等加载形式的,因此RequestManager中也有很多个load()方法的重载。但是这里我们不可能把每个load()方法的重载都看一遍,因此我们就只选其中一个加载图片URL字符串的load()方法来进行研究吧。

public class RequestManager implements LifecycleListener {

// 那么我们先来看load()方法,这个方法中的逻辑是非常简单的,只有一行代码,
// 就是先调用了fromString()方法,再调用load()方法,然后把传入的图片URL地址传进去。
// 而fromString()方法也极为简单,就是调用了loadGeneric()方法,并且指定参数为String.class,因为load()方法传入的是一个字符串参数。那么看上去,好像主要的工作都是在loadGeneric()方法中进行的了。
public DrawableTypeRequest load(String string) {
return (DrawableTypeRequest) fromString().load(string);
}

public DrawableTypeRequest fromString() {
return loadGeneric(String.class);
}

// 其实loadGeneric()方法也没几行代码,这里分别调用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法来获得ModelLoader对象。
// ModelLoader对象是用于加载图片的,而我们给load()方法传入不同类型的参数,这里也会得到不同的ModelLoader对象。
// 由于我们刚才传入的参数是String.class,因此最终得到的是StreamStringLoader对象,它是实现了ModelLoader接口的。
private DrawableTypeRequest loadGeneric(Class modelClass) {
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
throw new IllegalArgumentException("Unknown type " + modelClass + “. You must provide a Model of a type for”

  • " which there is a registered ModelLoader, if you are using a custom model, you must first call"
  • " Glide#register with a ModelLoaderFactory for your custom model class");
    }
    // loadGeneric()方法是要返回一个DrawableTypeRequest对象的,
    // 因此在loadGeneric()方法的最后又去new了一个DrawableTypeRequest对象,
    // 然后把刚才获得的ModelLoader对象,还有一大堆杂七杂八的东西都传了进去。具体每个参数的含义和作用就不解释了,我们只看主线流程。
    return optionsApplier.apply(
    new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
    glide, requestTracker, lifecycle, optionsApplier));
    }
    }

那么这个DrawableTypeRequest的作用是什么呢?我们来看下它的源码,如下所示:

public class DrawableTypeRequest extends DrawableRequestBuilder implements DownloadOptions {
private final ModelLoader<ModelType, InputStream> streamModelLoader;
private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
private final RequestManager.OptionsApplier optionsApplier;

private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class resourceClass,
Class transcodedClass,
ResourceTranscoder<Z, R> transcoder) {
if (streamModelLoader == null && fileDescriptorModelLoader == null) {
return null;
}

if (transcoder == null) {
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
ImageVideoModelLoader modelLoader = new ImageVideoModelLoader(streamModelLoader,
fileDescriptorModelLoader);
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
}

DrawableTypeRequest(Class modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}

/**

  • 最主要的就是它提供了asBitmap()和asGif()这两个方法。这两个方法我们在上一篇文章当中都是学过的,分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出,它们分别又创建了一个BitmapTypeRequest和GifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest。
    */
    public BitmapTypeRequest asBitmap() {
    return optionsApplier.apply(new BitmapTypeRequest(this, streamModelLoader,
    fileDescriptorModelLoader, optionsApplier));
    }

/**
*
*/
public GifTypeRequest asGif() {
return optionsApplier.apply(new GifTypeRequest(this, streamModelLoader, optionsApplier));
}


}

这个类中的代码本身就不多,我只是稍微做了一点简化。可以看到,最主要的就是它提供了asBitmap()和asGif()这两个方法。这两个方法我们在上一篇文章当中都是学过的,分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出,它们分别又创建了一个BitmapTypeRequest和GifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest。

好的,那么我们再回到RequestManager的load()方法中。刚才已经分析过了,fromString()方法会返回一个DrawableTypeRequest对象,接下来会调用这个对象的load()方法,把图片的URL地址传进去。但是我们刚才看到了,DrawableTypeRequest中并没有load()方法,那么很容易就能猜想到,load()方法是在父类当中的。

DrawableTypeRequest的父类是DrawableRequestBuilder,我们来看下这个类的源码:

public class DrawableRequestBuilder
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {

DrawableRequestBuilder(Context context, Class modelClass,
LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle) {
super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
// Default to animating.
crossFade();
}

public DrawableRequestBuilder thumbnail(
DrawableRequestBuilder<?> thumbnailRequest) {
super.thumbnail(thumbnailRequest);
return this;
}

@Override
public DrawableRequestBuilder thumbnail(
GenericRequestBuilder<?, ?, ?, GlideDrawable> thumbnailRequest) {
super.thumbnail(thumbnailRequest);
return this;
}

@Override
public DrawableRequestBuilder thumbnail(float sizeMultiplier) {
super.thumbnail(sizeMultiplier);
return this;
}

@Override
public DrawableRequestBuilder sizeMultiplier(float sizeMultiplier) {
super.sizeMultiplier(sizeMultiplier);
return this;
}

@Override
public DrawableRequestBuilder decoder(ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> decoder) {
super.decoder(decoder);
return this;
}

@Override
public DrawableRequestBuilder cacheDecoder(ResourceDecoder<File, GifBitmapWrapper> cacheDecoder) {
super.cacheDecoder(cacheDecoder);
return this;
}

@Override
public DrawableRequestBuilder encoder(ResourceEncoder encoder) {
super.encoder(encoder);
return this;
}

@Override
public DrawableRequestBuilder priority(Priority priority) {
super.priority(priority);
return this;
}

public DrawableRequestBuilder transform(BitmapTransformation… transformations) {
return bitmapTransform(transformations);
}

public DrawableRequestBuilder centerCrop() {
return transform(glide.getDrawableCenterCrop());
}

public DrawableRequestBuilder fitCenter() {
return transform(glide.getDrawableFitCenter());
}

public DrawableRequestBuilder bitmapTransform(Transformation… bitmapTransformations) {
GifBitmapWrapperTransformation[] transformations =
new GifBitmapWrapperTransformation[bitmapTransformations.length];
for (int i = 0; i < bitmapTransformations.length; i++) {
transformations[i] = new GifBitmapWrapperTransformation(glide.getBitmapPool(), bitmapTransformations[i]);
}
return transform(transformations);
}

@Override
public DrawableRequestBuilder transform(Transformation… transformation) {
super.transform(transformation);
return this;
}

@Override
public DrawableRequestBuilder transcoder(
ResourceTranscoder<GifBitmapWrapper, GlideDrawable> transcoder) {
super.transcoder(transcoder);
return this;
}

public final DrawableRequestBuilder crossFade() {
super.animate(new DrawableCrossFadeFactory());
return this;
}

public DrawableRequestBuilder crossFade(int duration) {
super.animate(new DrawableCrossFadeFactory(duration));
return this;
}

public DrawableRequestBuilder crossFade(int animationId, int duration) {
super.animate(new DrawableCrossFadeFactory(context, animationId,
duration));
return this;
}

@Override
public DrawableRequestBuilder dontAnimate() {
super.dontAnimate();
return this;
}

@Override
public DrawableRequestBuilder animate(ViewPropertyAnimation.Animator animator) {
super.animate(animator);
return this;
}

@Override
public DrawableRequestBuilder animate(int animationId) {
super.animate(animationId);
return this;
}

@Override
public DrawableRequestBuilder placeholder(int resourceId) {
super.placeholder(resourceId);
return this;
}

@Override
public DrawableRequestBuilder placeholder(Drawable drawable) {
super.placeholder(drawable);
return this;
}

@Override
public DrawableRequestBuilder fallback(Drawable drawable) {
super.fallback(drawable);
return this;
}

@Override
public DrawableRequestBuilder fallback(int resourceId) {
super.fallback(resourceId);
return this;
}

@Override
public DrawableRequestBuilder error(int resourceId) {
super.error(resourceId);
return this;
}

@Override
public DrawableRequestBuilder error(Drawable drawable) {
super.error(drawable);
return this;
}

@Override
public DrawableRequestBuilder listener(
RequestListener<? super ModelType, GlideDrawable> requestListener) {
super.listener(requestListener);
return this;
}
@Override
public DrawableRequestBuilder diskCacheStrategy(DiskCacheStrategy strategy) {
super.diskCacheStrategy(strategy);
return this;
}

@Override
public DrawableRequestBuilder skipMemoryCache(boolean skip) {
super.skipMemoryCache(skip);
return this;
}

@Override
public DrawableRequestBuilder override(int width, int height) {
super.override(width, height);
return this;
}

@Override
public DrawableRequestBuilder sourceEncoder(Encoder sourceEncoder) {
super.sourceEncoder(sourceEncoder);
return this;
}

@Override
public DrawableRequestBuilder dontTransform() {
super.dontTransform();
return this;
}

@Override
public DrawableRequestBuilder signature(Key signature) {
super.signature(signature);
return this;
}

@Override
public DrawableRequestBuilder load(ModelType model) {
super.load(model);
return this;
}

@Override
public DrawableRequestBuilder clone() {
return (DrawableRequestBuilder) super.clone();
}

@Override
public Target into(ImageView view) {
return super.into(view);
}

@Override
void applyFitCenter() {
fitCenter();
}

@Override
void applyCenterCrop() {
centerCrop();
}
}

DrawableRequestBuilder中有很多个方法,这些方法其实就是Glide绝大多数的API了。里面有不少我们在上篇文章中已经用过了,比如说placeholder()方法、error()方法、diskCacheStrategy()方法、override()方法等。当然还有很多暂时还没用到的API,我们会在后面的文章当中学习。

到这里,第二步load()方法也就分析结束了。为什么呢?因为你会发现DrawableRequestBuilder类中有一个into()方法(上述代码第220行),也就是说,最终load()方法返回的其实就是一个DrawableTypeRequest对象。那么接下来我们就要进行第三步了,分析into()方法中的逻辑。

2.3、总结

load方法最终做的就是进行一些初始化的操作,获得了一个DrawableTypeRequest对象,通过这个对象我们就可以获得图片请求的request,然后再接下来的into方法中使用。

3、into()
3.1、详解

如果说前面两步都是在准备开胃小菜的话,那么现在终于要进入主菜了,因为into()方法也是整个Glide图片加载流程中逻辑最复杂的地方。

不过从刚才的代码来看,into()方法中并没有任何逻辑,只有一句super.into(view)。那么很显然,into()方法的具体逻辑都是在DrawableRequestBuilder的父类当中了。

3.1、源码

DrawableRequestBuilder的父类是GenericRequestBuilder,我们来看一下GenericRequestBuilder类中的into()方法,如下所示:

public Target into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException(“You must pass in a non null View”);
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
// C A S E S − O M I T T E D CASES-OMITTED CASESOMITTED
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}

这里前面一大堆的判断逻辑我们都可以先不用管,等到后面文章讲transform的时候会再进行解释,现在我们只需要关注最后一行代码。最后一行代码先是调用了glide.buildImageViewTarget()方法,这个方法会构建出一个Target对象,Target对象则是用来最终展示图片用的,如果我们跟进去的话会看到如下代码:

Target buildImageViewTarget(ImageView imageView, Class transcodedClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}

这里其实又是调用了ImageViewTargetFactory的buildTarget()方法,我们继续跟进去,代码如下所示:

public class ImageViewTargetFactory {

@SuppressWarnings(“unchecked”)
public Target buildTarget(ImageView view, Class clazz) {
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target) new GlideDrawableImageViewTarget(view);
} else if (Bitmap.class.equals(clazz)) {
return (Target) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz

  • “, try .as*(Class).transcode(ResourceTranscoder)”);
    }
    }
    }

可以看到,在buildTarget()方法中会根据传入的class参数来构建不同的Target对象。那如果你要分析这个class参数是从哪儿传过来的,这可有得你分析了,简单起见我直接帮大家梳理清楚。这个class参数其实基本上只有两种情况,如果你在使用Glide加载图片的时候调用了asBitmap()方法,那么这里就会构建出BitmapImageViewTarget对象,否则的话构建的都是GlideDrawableImageViewTarget对象。至于上述代码中的DrawableImageViewTarget对象,这个通常都是用不到的,我们可以暂时不用管它。

也就是说,通过glide.buildImageViewTarget()方法,我们构建出了一个GlideDrawableImageViewTarget对象。那现在回到刚才into()方法的最后一行,可以看到,这里又将这个参数传入到了GenericRequestBuilder另一个接收Target对象的into()方法当中了。我们来看一下这个into()方法的源码:

public <Y extends Target> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
throw new IllegalArgumentException(“You must pass in a non null Target”);
}
if (!isModelSet) {
throw new IllegalArgumentException(“You must first set a model (try #load())”);
}
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
// 重点:Request是用来发出加载图片请求的,它是Glide中非常关键的一个组件。
requestTracker.runRequest(request);
return target;
}

这里我们还是只抓核心代码,其实只有两行是最关键的,第15行调用buildRequest()方法构建出了一个Request对象,还有第18行来执行这个Request。

Request是用来发出加载图片请求的,它是Glide中非常关键的一个组件。我们先来看buildRequest()方法是如何构建Request对象的:

private Request buildRequest(Target target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}

// buildRequest()方法的内部其实又调用了buildRequestRecursive()方法
private Request buildRequestRecursive(Target target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != 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()”);
    }
    // Recursive case: contains a potentially recursive thumbnail request builder.
    if (thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) {
    thumbnailRequestBuilder.animationFactory = animationFactory;
    }

if (thumbnailRequestBuilder.priority == null) {
thumbnailRequestBuilder.priority = getThumbnailPriority();
}

if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !Util.isValidDimensions(thumbnailRequestBuilder.overrideWidth,
thumbnailRequestBuilder.overrideHeight)) {
thumbnailRequestBuilder.override(overrideWidth, overrideHeight);
}

ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
// Guard against infinite recursion.
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
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(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.‘’
// 这里调用了obtainRequest()方法来获取一个Request对象,而obtainRequest()方法中又去调用了GenericRequest的obtain()方法。
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}

private Request obtainRequest(Target target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
fallbackDrawable,
fallbackResource,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}

可以看到,buildRequest()方法的内部其实又调用了buildRequestRecursive()方法,而buildRequestRecursive()方法中的代码虽然有点长,但是其中90%的代码都是在处理缩略图的。如果我们只追主线流程的话,那么只需要看第47行代码就可以了。这里调用了obtainRequest()方法来获取一个Request对象,而obtainRequest()方法中又去调用了GenericRequestobtain()方法。注意这个obtain()方法需要传入非常多的参数,而其中很多的参数我们都是比较熟悉的,像什么placeholderId、errorPlaceholder、diskCacheStrategy等等。因此,我们就有理由猜测,刚才在load()方法中调用的所有API,其实都是在这里组装到Request对象当中的。那么我们进入到这个GenericRequest的obtain()方法瞧一瞧:

public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,
ResourceCallback {

public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
LoadProvider<A, T, Z, R> loadProvider,
A model,
Key signature,
Context context,
Priority priority,
Target target,
float sizeMultiplier,
Drawable placeholderDrawable,
int placeholderResourceId,
Drawable errorDrawable,
int errorResourceId,
Drawable fallbackDrawable,
int fallbackResourceId,
RequestListener<? super A, R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
Transformation transformation,
Class transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategy diskCacheStrategy) {
@SuppressWarnings(“unchecked”)
GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
if (request == null) {
// 33行:
request = new GenericRequest<A, T, Z, R>();
}
request.init(loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderResourceId,
errorDrawable,
errorResourceId,
fallbackDrawable,
fallbackResourceId,
requestListener,
requestCoordinator,
engine,
transformation,
transcodeClass,
isMemoryCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
return request;
}
}

可以看到,这里在第33行去new了一个GenericRequest对象,并在最后一行返回,也就是说,obtain()方法实际上获得的就是一个GenericRequest对象。另外这里又在第35行调用了GenericRequest的init(),里面主要就是一些赋值的代码,将传入的这些参数赋值到GenericRequest的成员变量当中,我们就不再跟进去看了。

好,那现在解决了构建Request对象的问题,接下来我们看一下这个Request对象又是怎么执行的。回到刚才的into()方法,你会发现在第18行调用了requestTracker.runRequest()方法来去执行这个Request,那么我们跟进去瞧一瞧,如下所示:

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节

整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

overrideHeight,
diskCacheStrategy);
return request;
}
}

可以看到,这里在第33行去new了一个GenericRequest对象,并在最后一行返回,也就是说,obtain()方法实际上获得的就是一个GenericRequest对象。另外这里又在第35行调用了GenericRequest的init(),里面主要就是一些赋值的代码,将传入的这些参数赋值到GenericRequest的成员变量当中,我们就不再跟进去看了。

好,那现在解决了构建Request对象的问题,接下来我们看一下这个Request对象又是怎么执行的。回到刚才的into()方法,你会发现在第18行调用了requestTracker.runRequest()方法来去执行这个Request,那么我们跟进去瞧一瞧,如下所示:

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节

[外链图片转存中…(img-hG4Otexp-1715061531997)]

整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值