Android图片加载框架最全解析,从源码的角度理解Glide的执行流程

知识为进步之母,而进步又为富强之源泉。这篇文章主要讲述Android图片加载框架最全解析,从源码的角度理解Glide的执行流程相关的知识,希望能为你提供帮助。
转载请注明出处: http://blog.csdn.net/guolin_blog/article/details/53939176

本文同步发表于我的微信公众号, 扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注, 每天都有文章更新。
在本系列的上一篇文章中, 我们学习了Glide的基本用法, 体验了这个图片加载框架的强大功能, 以及它非常简便的API。还没有看过上一篇文章的朋友, 建议先去阅读 Android图片加载框架最全解析( 一) , Glide的基本用法 。
在多数情况下, 我们想要在界面上加载并展示一张图片只需要一行代码就能实现, 如下所示:
Glide.with(this).load(url).into(imageView);

虽说只有这简简单单的一行代码, 但大家可能不知道的是, Glide在背后帮我们默默执行了成吨的工作。这个形容词我想了很久, 因为我觉得用非常多这个形容词不足以描述Glide背后的工作量, 我查到的英文资料是用tons of work来进行形容的, 因此我觉得这里使用成吨来形容更加贴切一些。
虽说我们在平时使用Glide的时候格外地简单和方便, 但是知其然也要知其所以然。那么今天我们就来解析一下Glide的源码, 看看它在这些简单用法的背后, 到底执行了多么复杂的工作。
如何阅读源码 在开始解析Glide源码之前, 我想先和大家谈一下该如何阅读源码, 这个问题也是我平时被问得比较多的, 因为很多人都觉得阅读源码是一件比较困难的事情。
那么阅读源码到底困难吗? 这个当然主要还是要视具体的源码而定。比如同样是图片加载框架, 我读Volley的源码时就感觉酣畅淋漓, 并且对Volley的架构设计和代码质量深感佩服。读Glide的源码时却让我相当痛苦, 代码极其难懂。当然这里我并不是说Glide的代码写得不好, 只是因为Glide和复杂程度和Volley完全不是在一个量级上的。
那么, 虽然源码的复杂程度是外在的不可变条件, 但我们却可以通过一些技巧来提升自己阅读源码的能力。这里我和大家分享一下我平时阅读源码时所使用的技巧, 简单概括就是八个字: 抽丝剥茧、点到即止。应该认准一个功能点, 然后去分析这个功能点是如何实现的。但只要去追寻主体的实现逻辑即可, 千万不要试图去搞懂每一行代码都是什么意思, 那样很容易会陷入到思维黑洞当中, 而且越陷越深。因为这些庞大的系统都不是由一个人写出来的, 每一行代码都想搞明白, 就会感觉自己是在盲人摸象, 永远也研究不透。如果只是去分析主体的实现逻辑, 那么就有比较明确的目的性, 这样阅读源码会更加轻松, 也更加有成效。
而今天带大家阅读的Glide源码就非常适合使用这个技巧, 因为Glide的源码太复杂了, 千万不要试图去搞明白它每行代码的作用, 而是应该只分析它的主体实现逻辑。那么我们本篇文章就先确立好一个目标, 就是要通过阅读源码搞明白下面这行代码:
Glide.with(this).load(url).into(imageView);

到底是如何实现将一张网络图片展示到ImageView上面的。先将Glide的一整套图片加载机制的基本流程梳理清楚, 然后我们再通过后面的几篇文章具体去了解Glide源码方方面面的细节。
准备好了吗? 那么我们现在开始。
源码下载 既然是要阅读Glide的源码, 那么我们自然需要先将Glide的源码下载下来。其实如果你是使用在build.gradle中添加依赖的方式将Glide引入到项目中的, 那么源码自动就已经下载下来了, 在android Studio中就可以直接进行查看。
不过, 使用添加依赖的方式引入的Glide, 我们只能看到它的源码, 但不能做任何的修改, 如果你还需要修改它的源码的话, 可以到GitHub上面将它的完整源码下载下来。
Glide的GitHub主页的地址是: https://github.com/bumptech/glide
不过在这个地址下载到的永远都是最新的源码, 有可能还正在处于开发当中。而我们整个系列都是使用Glide 3.7.0这个版本来进行讲解的, 因此如果你需要专门去下载3.7.0版本的源码, 可以到这个地址进行下载: https://github.com/bumptech/glide/tree/v3.7.0
开始阅读 我们在上一篇文章中已经学习过了, Glide最基本的用法就是三步走: 先with(), 再load(), 最后into()。那么我们开始一步步阅读这三步走的源码, 先从with()看起。
1. with() with()方法是Glide类中的一组静态方法, 它有好几个方法重载, 我们来看一下Glide类中所有with()方法的方法重载:
public class Glide {...public static RequestManager with(Context context) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(context); }public static RequestManager with(Activity activity) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); 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()方法的重载种类非常多, 既可以传入Activity, 也可以传入Fragment或者是Context。每一个with()方法重载的代码都非常简单, 都是先调用RequestManagerRetriever的静态get()方法得到一个RequestManagerRetriever对象, 这个静态get()方法就是一个单例实现, 没什么需要解释的。然后再调用RequestManagerRetriever的实例get()方法, 去获取RequestManager对象。
而RequestManagerRetriever的实例get()方法中的逻辑是什么样的呢? 我们一起来看一看:
public class RequestManagerRetriever implements Handler.Callback {private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever(); private volatile RequestManager applicationManager; .../** * Retrieves and returns the RequestManagerRetriever singleton. */ public static RequestManagerRetriever get() { return INSTANCE; }private RequestManager getApplicationManager(Context context) { // Either an application context or we' re on a background thread. if (applicationManager = = null) { synchronized (this) { if (applicationManager = = null) { // Normally pause/resume is taken care of by the fragment we add to the fragment or activity. // However, in this case since the manager attached to the application will not receive lifecycle // events, we must force the manager to start resumed using ApplicationLifecycle. applicationManager = new RequestManager(context.getApplicationContext(), new ApplicationLifecycle(), new EmptyRequestManagerTreeNode()); } } } return applicationManager; }public RequestManager get(Context context) { if (context = = null) { throw new IllegalArgumentException(" You cannot start a load on a null Context" ); } else if (Util.isOnMainThread() & & !(context instanceof Application)) { if (context instanceof FragmentActivity) { return get((FragmentActivity) context); } else if (context instanceof Activity) { return get((Activity) context); } else if (context instanceof ContextWrapper) { return get(((ContextWrapper) context).getBaseContext()); } } return getApplicationManager(context); }public RequestManager get(FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm); } }public RequestManager get(Fragment fragment) { if (fragment.getActivity() = = null) { throw new IllegalArgumentException(" You cannot start a load on a fragment before it is attached" ); } if (Util.isOnBackgroundThread()) { return get(fragment.getActivity().getApplicationContext()); } else { FragmentManager fm = fragment.getChildFragmentManager(); return supportFragmentGet(fragment.getActivity(), fm); } }@ TargetApi(Build.VERSION_CODES.HONEYCOMB) public RequestManager get(Activity activity) { if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm); } }@ TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) private static void assertNotDestroyed(Activity activity) { if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.JELLY_BEAN_MR1 & & activity.isDestroyed()) { throw new IllegalArgumentException(" You cannot start a load for a destroyed activity" ); } }@ TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public RequestManager get(android.app.Fragment fragment) { if (fragment.getActivity() = = null) { throw new IllegalArgumentException(" You cannot start a load on a fragment before it is attached" ); } if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { return get(fragment.getActivity().getApplicationContext()); } else { android.app.FragmentManager fm = fragment.getChildFragmentManager(); return fragmentGet(fragment.getActivity(), fm); } }@ TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) { RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current = = null) { current = pendingRequestManagerFragments.get(fm); if (current = = null) { current = new RequestManagerFragment(); pendingRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }@ TargetApi(Build.VERSION_CODES.HONEYCOMB) RequestManager fragmentGet(Context context, android.app.FragmentManager fm) { RequestManagerFragment current = getRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); if (requestManager = = null) { requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager; }SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current = = null) { current = pendingSupportRequestManagerFragments.get(fm); if (current = = null) { current = new SupportRequestManagerFragment(); pendingSupportRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }RequestManager supportFragmentGet(Context context, FragmentManager fm) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); if (requestManager = = null) { requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager; }... }

上述代码虽然看上去逻辑有点复杂, 但是将它们梳理清楚后还是很简单的。RequestManagerRetriever类中看似有很多个get()方法的重载, 什么Context参数, Activity参数, Fragment参数等等, 实际上只有两种情况而已, 即传入Application类型的参数, 和传入非Application类型的参数。
我们先来看传入Application参数的情况。如果在Glide.with()方法中传入的是一个Application对象, 那么这里就会调用带有Context参数的get()方法重载, 然后会在第44行调用getApplicationManager()方法来获取一个RequestManager对象。其实这是最简单的一种情况, 因为Application对象的生命周期即应用程序的生命周期, 因此Glide并不需要做什么特殊的处理, 它自动就是和应用程序的生命周期是同步的, 如果应用程序关闭的话, Glide的加载也会同时终止。
接下来我们看传入非Application参数的情况。不管你在Glide.with()方法中传入的是Activity、FragmentActivity、v4包下的Fragment、还是app包下的Fragment, 最终的流程都是一样的, 那就是会向当前的Activity当中添加一个隐藏的Fragment。具体添加的逻辑是在上述代码的第117行和第141行, 分别对应的app包和v4包下的两种Fragment的情况。那么这里为什么要添加一个隐藏的Fragment呢? 因为Glide需要知道加载的生命周期。很简单的一个道理, 如果你在某个Activity上正在加载着一张图片, 结果图片还没加载出来, Activity就被用户关掉了, 那么图片还应该继续加载吗? 当然不应该。可是Glide并没有办法知道Activity的生命周期, 于是Glide就使用了添加隐藏Fragment的这种小技巧, 因为Fragment的生命周期和Activity是同步的, 如果Activity被销毁了, Fragment是可以监听到的, 这样Glide就可以捕获这个事件并停止图片加载了。
这里额外再提一句, 从第48行代码可以看出, 如果我们是在非主线程当中使用的Glide, 那么不管你是传入的Activity还是Fragment, 都会被强制当成Application来处理。不过其实这就属于是在分析代码的细节了, 本篇文章我们将会把目光主要放在Glide的主线工作流程上面, 后面不会过多去分析这些细节方面的内容。
总体来说, 第一个with()方法的源码还是比较好理解的。其实就是为了得到一个RequestManager对象而已, 然后Glide会根据我们传入with()方法的参数来确定图片加载的生命周期, 并没有什么特别复杂的逻辑。不过复杂的逻辑还在后面等着我们呢, 接下来我们开始分析第二步, load()方法。
2. load() 由于with()方法返回的是一个RequestManager对象, 那么很容易就能想到, load()方法是在RequestManager类当中的, 所以说我们首先要看的就是RequestManager这个类。不过在上一篇文章中我们学过, Glide是支持图片URL字符串、图片本地路径等等加载形式的, 因此RequestManager中也有很多个load()方法的重载。但是这里我们不可能把每个load()方法的重载都看一遍, 因此我们就只选其中一个加载图片URL字符串的load()方法来进行研究吧。
【Android图片加载框架最全解析,从源码的角度理解Glide的执行流程】RequestManager类的简化代码如下所示:
public class RequestManager implements LifecycleListener {.../** * Returns a request builder to load the given {@ link String}. * signature. * * @ see #fromString() * @ see #load(Object) * * @ param string A file path, or a uri or url handled by {@ link com.bumptech.glide.load.model.UriLoader}. */ public DrawableTypeRequest< String> load(String string) { return (DrawableTypeRequest< String> ) fromString().load(string); }/** * Returns a request builder that loads data from {@ link String}s using an empty signature. * * < p> *Note - this method caches data using only the given String as the cache key. If the data is a Uri outside of *your control, or you otherwise expect the data represented by the given String to change without the String *identifier changing, Consider using *{@ link GenericRequestBuilder#signature(Key)} to mixin a signature *you create that identifies the data currently at the given String that will invalidate the cache if that data *changes. Alternatively, using {@ link DiskCacheStrategy#NONE} and/or *{@ link DrawableRequestBuilder#skipMemoryCache(boolean)} may be appropriate. * < /p> * * @ see #from(Class) * @ see #load(String) */ public DrawableTypeRequest< String> fromString() { return loadGeneric(String.class); }private < T> DrawableTypeRequest< T> loadGeneric(Class< T> 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" ); } return optionsApplier.apply( new DrawableTypeRequest< T> (modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)); }...}

RequestManager类的代码是非常多的, 但是经过我这样简化之后, 看上去就比较清爽了。在我们只探究加载图片URL字符串这一个load()方法的情况下, 那么比较重要的方法就只剩下上述代码中的这三个方法。
那么我们先来看load()方法, 这个方法中的逻辑是非常简单的, 只有一行代码, 就是先调用了fromString()方法, 再调用load()方法, 然后把传入的图片URL地址传进去。而fromString()方法也极为简单, 就是调用了loadGeneric()方法, 并且指定参数为String.class, 因为load()方法传入的是一个字符串参数。那么看上去, 好像主要的工作都是在loadGeneric()方法中进行的了。
其实loadGeneric()方法也没几行代码, 这里分别调用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法来获得ModelLoader对象。ModelLoader对象是用于加载图片的, 而我们给load()方法传入不同类型的参数, 这里也会得到不同的ModelLoader对象。不过buildStreamModelLoader()方法内部的逻辑还是蛮复杂的, 这里就不展开介绍了, 要不然篇幅实在收不住, 感兴趣的话你可以自己研究。由于我们刚才传入的参数是String.class, 因此最终得到的是StreamStringLoader对象, 它是实现了ModelLoader接口的。
最后我们可以看到, loadGeneric()方法是要返回一个DrawableTypeRequest对象的, 因此在loadGeneric()方法的最后又去new了一个DrawableTypeRequest对象, 然后把刚才获得的ModelLoader对象, 还有一大堆杂七杂八的东西都传了进去。具体每个参数的含义和作用就不解释了, 我们只看主线流程。
那么这个DrawableTypeRequest的作用是什么呢? 我们来看下它的源码, 如下所示:
public class DrawableTypeRequest< ModelType> extends DrawableRequestBuilder< ModelType> 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< Z> resourceClass, Class< R> 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< A> modelLoader = new ImageVideoModelLoader< A> (streamModelLoader, fileDescriptorModelLoader); return new FixedLoadProvider< A, ImageVideoWrapper, Z, R> (modelLoader, transcoder, dataLoadProvider); }DrawableTypeRequest(Class< ModelType> 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; }/** * Attempts to always load the resource as a {@ link android.graphics.Bitmap}, even if it could actually be animated. * * @ return A new request builder for loading a {@ link android.graphics.Bitmap} */ public BitmapTypeRequest< ModelType> asBitmap() { return optionsApplier.apply(new BitmapTypeRequest< ModelType> (this, streamModelLoader, fileDescriptorModelLoader, optionsApplier)); }/** * Attempts to always load the resource as a {@ link com.bumptech.glide.load.resource.gif.GifDrawable}. * < p> *If the underlying data is not a GIF, this will fail. As a result, this should only be used if the model *represents an animated GIF and the caller wants to interact with the GIfDrawable directly. Normally using *just an {@ link DrawableTypeRequest} is sufficient because it will determine whether or *not the given data represents an animated GIF and return the appropriate animated or not animated *{@ link android.graphics.drawable.Drawable} automatically. * < /p> * * @ return A new request builder for loading a {@ link com.bumptech.glide.load.resource.gif.GifDrawable}. */ public GifTypeRequest< ModelType> asGif() { return optionsApplier.apply(new GifTypeRequest< ModelType> (this, streamModelLoader, optionsApplier)); }... }

这个类中的代码本身就不多, 我只是稍微做了一点简化。可以看到, 最主要的就是它提供了asBitmap()和asGif()这两个方法。这两个方法我们在上一篇文章当中都是学过的, 分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出, 它们分别又创建了一个BitmapTypeRequest和GifTypeRequest, 如果没有进行强制指定的话, 那默认就是使用DrawableTypeRequest。
好的, 那么我们再回到RequestManager的load()方法中。刚才已经分析过了, fromString()方法会返回一个DrawableTypeRequest对象, 接下来会调用这个对象的load()方法, 把图片的URL地址传进去。但是我们刚才看到了, DrawableTypeRequest中并没有load()方法, 那么很容易就能猜想到, load()方法是在父类当中的。
DrawableTypeRequest的父类是DrawableRequestBuilder, 我们来看下这个类的源码:
public class DrawableRequestBuilder< ModelType> extends GenericRequestBuilder< ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> implements BitmapOptions, DrawableOptions {DrawableRequestBuilder(Context context, Class< ModelType> 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< ModelType> thumbnail( DrawableRequestBuilder< ?> thumbnailRequest) { super.thumbnail(thumbnailRequest); return this; }@ Override public DrawableRequestBuilder< ModelType> thumbnail( GenericRequestBuilder< ?, ?, ?, GlideDrawable> thumbnailRequest) { super.thumbnail(thumbnailRequest); return this; }@ Override public DrawableRequestBuilder< ModelType> thumbnail(float sizeMultiplier) { super.thumbnail(sizeMultiplier); return this; }@ Override public DrawableRequestBuilder< ModelType> sizeMultiplier(float sizeMultiplier) { super.sizeMultiplier(sizeMultiplier); return this; }@ Override public DrawableRequestBuilder< ModelType> decoder(ResourceDecoder< ImageVideoWrapper, GifBitmapWrapper> decoder) { super.decoder(decoder); return this; }@ Override public DrawableRequestBuilder< ModelType> cacheDecoder(ResourceDecoder< File, GifBitmapWrapper> cacheDecoder) { super.cacheDecoder(cacheDecoder); return this; }@ Override public DrawableRequestBuilder< ModelType> encoder(ResourceEncoder< GifBitmapWrapper> encoder) { super.encoder(encoder); return this; }@ Override public DrawableRequestBuilder< ModelType> priority(Priority priority) { super.priority(priority); return this; }public DrawableRequestBuilder< ModelType> transform(BitmapTransformation... transformations) { return bitmapTransform(transformations); }public DrawableRequestBuilder< ModelType> centerCrop() { return transform(glide.getDrawableCenterCrop()); }public DrawableRequestBuilder< ModelType> fitCenter() { return transform(glide.getDrawableFitCenter()); }public DrawableRequestBuilder< ModelType> bitmapTransform(Transformation< Bitmap> ... 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< ModelType> transform(Transformation< GifBitmapWrapper> ... transformation) { super.transform(transformation); return this; }@ Override public DrawableRequestBuilder< ModelType> transcoder( ResourceTranscoder< GifBitmapWrapper, GlideDrawable> transcoder) { super.transcoder(transcoder); return this; }public final DrawableRequestBuilder< ModelType> crossFade() { super.animate(new DrawableCrossFadeFactory< GlideDrawable> ()); return this; }public DrawableRequestBuilder< ModelType> crossFade(int duration) { super.animate(new DrawableCrossFadeFactory< GlideDrawable> (duration)); return this; }public DrawableRequestBuilder< ModelType> crossFade(int animationId, int duration) { super.animate(new DrawableCrossFadeFactory< GlideDrawable> (context, animationId, duration)); return this; }@ Override public DrawableRequestBuilder< ModelType> dontAnimate() { super.dontAnimate(); return this; }@ Override public DrawableRequestBuilder< ModelType> animate(ViewPropertyAnimation.Animator animator) { super.animate(animator); return this; }@ Override public DrawableRequestBuilder< ModelType> animate(int animationId) { super.animate(animationId); return this; }@ Override public DrawableRequestBuilder< ModelType> placeholder(int resourceId) { super.placeholder(resourceId); return this; }@ Override public DrawableRequestBuilder< ModelType> placeholder(Drawable drawable) { super.placeholder(drawable); return this; }@ Override public DrawableRequestBuilder< ModelType> fallback(Drawable drawable) { super.fallback(drawable); return this; }@ Override public DrawableRequestBuilder< ModelType> fallback(int resourceId) { super.fallback(resourceId); return this; }@ Override public DrawableRequestBuilder< ModelType> error(int resourceId) { super.error(resourceId); return this; }@ Override public DrawableRequestBuilder< ModelType> error(Drawable drawable) { super.error(drawable); return this; }@ Override public DrawableRequestBuilder< ModelType> listener( RequestListener< ? super ModelType, GlideDrawable> requestListener) { super.listener(requestListener); return this; } @ Override public DrawableRequestBuilder< ModelType> diskCacheStrategy(DiskCacheStrategy strategy) { super.diskCacheStrategy(strategy); return this; }@ Override public DrawableRequestBuilder< ModelType> skipMemoryCache(boolean skip) { super.skipMemoryCache(skip); return this; }@ Override public DrawableRequestBuilder< ModelType> override(int width, int height) { super.override(width, height); return this; }@ Override public DrawableRequestBuilder< ModelType> sourceEncoder(Encoder< ImageVideoWrapper> sourceEncoder) { super.sourceEncoder(sourceEncoder); return this; }@ Override public DrawableRequestBuilder< ModelType> dontTransform() { super.dontTransform(); return this; }@ Override public DrawableRequestBuilder< ModelType> signature(Key signature) { super.signature(signature); return this; }@ Override public DrawableRequestBuilder< ModelType> load(ModelType model) { super.load(model); return this; }@ Override public DrawableRequestBuilder< ModelType> clone() { return (DrawableRequestBuilder< ModelType> ) super.clone(); }@ Override public Target< GlideDrawable> 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()方法中的逻辑。
3. into() 如果说前面两步都是在准备开胃小菜的话, 那么现在终于要进入主菜了, 因为into()方法也是整个Glide图片加载流程中逻辑最复杂的地方。
不过从刚才的代码来看, into()方法中并没有任何逻辑, 只有一句super.into(view)。那么很显然, into()方法的具体逻辑都是在DrawableRequestBuilder的父类当中了。
DrawableRequestBuilder的父类是GenericRequestBuilder, 我们来看一下GenericRequestBuilder类中的into()方法, 如下所示:
public Target< TranscodeType> 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; //$CASES-OMITTED$ default: // Do nothing. } } return into(glide.buildImageViewTarget(view, transcodeClass)); }

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

这里其实又是调用了ImageViewTargetFactory的buildTarget()方法, 我们继续跟进去, 代码如下所示:
public class ImageViewTargetFactory {@ SuppressWarnings(" unchecked" ) public < Z> Target< Z> buildTarget(ImageView view, Class< Z> clazz) { if (GlideDrawable.class.isAssignableFrom(clazz)) { return (Target< Z> ) new GlideDrawableImageViewTarget(view); } else if (Bitmap.class.equals(clazz)) { return (Target< Z> ) new BitmapImageViewTarget(view); } else if (Drawable.class.isAssignableFrom(clazz)) { return (Target< Z> ) 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< TranscodeType> > 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); requestTracker.runRequest(request); return target; }

这里我们还是只抓核心代码, 其实只有两行是最关键的, 第15行调用buildRequest()方法构建出了一个Request对象, 还有第18行来执行这个Request。
Request是用来发出加载图片请求的, 它是Glide中非常关键的一个组件。我们先来看buildRequest()方法是如何构建Request对象的:
private Request buildRequest(Target< TranscodeType> target) { if (priority = = null) { priority = Priority.NORMAL; } return buildRequestRecursive(target, null); }private Request buildRequestRecursive(Target< TranscodeType> 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. return obtainRequest(target, sizeMultiplier, priority, parentCoordinator); } }private Request obtainRequest(Target< TranscodeType> 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()方法中又去调用了GenericRequest的obtain()方法。注意这个obtain()方法需要传入非常多的参数, 而其中很多的参数我们都是比较熟悉的, 像什么placeholderId、errorPlaceholder、diskCacheStrategy等等。因此, 我们就有理由猜测, 刚才在load()方法中调用的所有API, 其实都是在这里组装到Request对象当中的。那么我们进入到这个GenericRequest的obtain()方法瞧一瞧:
public final class GenericRequest< A, T, Z, R>

    推荐阅读