Glide源码分析(一)

概述

在众多的图片加载的框架中,个人觉得Glide是表现的最好的,尤其是它缓存策略的设计,今天来根据源码来看一下Glide里面是如何运作的。由于Glide代码十分的庞大,而且隐晦难懂。这里主要是理解其中的含义,点到为止。该系列分为两篇来记录:
Glide源码分析(一)
Glide源码分析(二)

思维导图


源码分析

1
Glide.with(上下文).load("图片路径").into(ImageView);

with()

在with方法中,传入的参数可以有Context,Activity,Fragment和View。这与Picasso不同的是,Picasso只能传入Context,有一定的局限性。
Glide.class

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
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}

@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}

@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}

@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}

@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}

//。。。。。

@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();

可以看出都会返回RequestManager,而且不论传入什么都会当成转成Context处理。
RequestManagerRetriever.class

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
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull Activity activity) {

//.......

assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));

//.......
}

@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
@Deprecated
@NonNull
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}

可以看到在这两个方法做了相同的事:添加一个新的Fragment—RequestManagerFragment到当前页面;而这个Fragment的作用就是为了方便Glide控制生命周期,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了。
至此 我们了解了Glide.with()方法背后的操作。一系列操作最终得到的是RequestManager。接下来看load()。

load()

RequestManager.class:

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
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {//图片路径
return asDrawable().load(string);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {//加载bitmap
return asDrawable().load(bitmap);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {//加载本地的drawable
return asDrawable().load(drawable);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Uri uri) {//Uri的形式
return asDrawable().load(uri);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable File file) {
return asDrawable().load(file);
}

@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}

@CheckResult
public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}

这里可以看出Glide支持加载各种各样的图片资源,包括网络图片、本地图片、Uri对象,Url对象,String字符串等。
其返回的是RequestBuilder,而TranscodeType包含有Flie、Drawable、gif,概括了图片的各种形式。

总结

总结一下,首先Glide.with(Activity),指定了Activity,创建新的Fragment依附于Activity,其目的就是绑定了Activity的生命周期,当该Activity销毁或暂停的时候,Glide也会及时取消或者暂停加载图片。
同时with()返回一个RequestManager,在load()提供加载的路径,或者直接指定本地的Drawable,返回RequestBuilder,后续会在RequestBuilder.into(ImageView)给图片资源指定载体ImageView。
在下一篇《Glide源码分析(二)》具体分析。