第三方-Glide源码解读(记录)

“抽丝剥茧,点到即止”

阅读源码应认准一个功能点,然后去分析这个功能是如何实现的。但只要去追寻主体的实现逻辑即可,不要试图搞懂每一行代码。

Glide源码就定一个以下目标:

1
Glide.with(this).load(url).into(imageView);

with()

with()方法是 Glide 类中的一组静态方法,它有好几个方法重载,我们来看一下 Glide 类中所

有 with()方法的方法重载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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()的重载种类非常多。每个with()方法重载的代码都非常简单,都是先调用RequestManagerRetriever的静态get()得到对象,这个静态get()方法就是一个单例实现。再调用RequestManagerRetriever的实例的get()方法,去获取RequestManager对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
public class RequestManagerRetriever implements Handler.Callback{
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
private volatile RequestManager applicationManager;
...
/**
* Retrieves and returns the RequestManagerRetriever sigleton.
*/
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 caare 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 RequestManger 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;
}
...
}

上述代码看起来逻辑优点复杂,其实分两种情况:传入Application类型的参数,传入非Application类型的参数。

Glide.with()传入Application对象,那么这里会调用带有Context参数的get()方法重载,会调用getApplicationManager()获取RequestManager对象。另外,因为Application对象的生命周期即应用程序的生命周期,所以 Glide 不需要做特殊处理,它自动就是和应用程序的生命周期是同步的,如果应用程序关闭的话,Glide的加载也会同时终止。

Glide.with()传入非Application参数情况,不管传入的是ActivityFragmentAcitivityv4包下的Fragment、还是app包下的Fragment,最终都是向当前Activity中添加一个隐藏的Fragment。如此设计的原因是Glide需要知道加载的生命周期,若图片还没加载出来activity就结束了那么就不用加载图片了。当时因为Glide无法知道Activity的生命周期,所以借助添加隐藏Fragment的小技巧,Fragment的生命周期和Activity的同步,可以监听到Activity的销毁,只有Glide就可以捕获这个事件并停止图片加载了。

另外,如果在非主线程当中使用Glide,那么不管传入的是Activity还是Fragment,都会被强制当成Application来处理。

总体来说,第一个with()方法的源码就是为了得到一个RequestManager对象,然后Glide会根据传入with()的参数来确定图片加载的生命周期。

load()

由于with()返回的是RequestManager对象,那么容易想到load()是在RequestManager类中。Glide支持片URL字符串、图片本地路径等等加载形式,我们选其中一个加载图片URL字符串的load()来研究。

RequestManager类简化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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 对象。由于我们刚才传入的参 数是 String.class,因此最终得到的是 StreamStringLoader 对象,它是实现了 ModelLoader 接口的。

最后我们可以看到,loadGeneric()方法是要返回一个 DrawableTypeRequest 对象的,因此在loadGeneric()方法的最后又去 new 了一个 DrawableTypeRequest 对象,然后把刚才获得的 ModelLoader 对象,还有一大堆杂七杂八的东西都传了进去。具体每个参数的含义和作用就不解释了,我们只看主线流程。

DrawableTypeRequest 的作用是什么呢?我们来看下它的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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()这两个方法。这两个方法我们在上一篇文章当中都是学过的,分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出,它们分别又创建了一个BitmapTypeRequestGifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
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()方法中的逻辑。

into()

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 对象则是用来最终展示图片用的,如果我们跟进去的话会看到如下代码:

1
2
3
<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) { 
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()方法的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 行来执行这个 RequestRequest 是用来发出加载图片请求的,它是 Glide 中非常关键的一个组件。

我们先来看buildRequest()方法是如何构建 Request 对象的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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() 方 法 中 又 去 调 用 了GenericRequestobtain()方法。注意这个 obtain()方法需要传入非常多的参数,而其中很多的参数我们都是比较熟悉的,像什么 placeholderIderrorPlaceholderdiskCacheStrategy 等等。因此,我们就有理由猜测,刚才在 load()方法中调用的所有 API,其实都是在这里组装到 Request 对象当中的。

那么我们进入到这个 GenericRequestobtain()方法瞧一瞧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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<R> 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<Z> transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R> 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) {
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 行调用了GenericRequestinit(),里面主要就是一些赋值的代码,将传入的这些参数赋值到GenericRequest 的成员变量当中,我们就不再跟进去看了。

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

1
2
3
4
5
6
7
8
9
10
11
/**
* Starts tracking the given request.
*/
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}

这里有一个简单的逻辑判断,就是先判断 Glide 当前是不是处理暂停状态,如果不是暂停状态就调用 Request 的 begin()方法来执行 Request,否则的话就先将 Request 添加到待执行队列里面,等暂停状态解除了之后再执行。

暂停请求的功能仍然不是这篇文章所关心的,这里就直接忽略了,我们重点来看这个 begin() 方法。由于当前的 Request 对象是一个 GenericRequest,因此这里就需要看 GenericRequest 中的 begin()方法了,如下所示: