0%

Glide

逐步分析

Glide.with(……)

Glide.with() 有下面几种实现方式。

1
2
3
4
5
1. Glide.with(Context context)
2. Glide.with(Activity activity)
3. Glide.with(FragmentActivity activity)
4. Glide.with(android.app.Fragment fragment)
5. Glide.with(View view)

所以的方法实现也是很类似,都是调用同一个方法

1
2
3
public static RequestManager with(Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}

再看一下 getRetriever() 方法

1
2
3
4
5
6
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
……
省略一些判空检查
——
return Glide.get(context).getRequestManagerRetriever();
}

其中 Glide.get(context) 主要用来初始化 Glide 的全局单利对象,以及一些配置。

getRequestManagerRetriever() 则是返回 Glide 对象的 requestManagerRetriever 对象。

然后看一下 requestManagerRetriever.get() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
}

get() 方法会根据传入的 context 对象和当前线程,创建不同的 RequestManager 实例

1
2
3
4
5
1. 非 UI 线程,返回 applicationManager 对象,能感知 Application 生命周期。
2. UI 线程,如果 context 是 Activity 、FragmentActivity
则会创建一个能感知对应 Activity 的 RequestManager。
3. UI 线程,如果 Context 是 Fragment、android.support.v4.app.Fragment
则会创建一个能感知对应 Fragment 生命周期 的 RequestManager。

这里反复提到了一个 感知生命 xx 周期,也是 Glide 的一个特性。

1
2
3
Glide 在加载资源的时候,如果是在 Activity、Fragment 这一类有生命周期的组件上进行。
当 Activity、Fragment 等组件进入不可见,或者已经销毁的时候,Glide 会停止加载资源。
Application 的生命周期贯穿整个应用,所以 applicationManager 只有在应用程序关闭的时候终止加载。

所以尽量不要在非 UI 线程使用 Glide 加载图片,尽量使用 Activity、Fragment 等带有生命周期的组件配合 Glide 使用。

Glide 如何获得 Activity、Fragment 生命周期回调

在 各种 requestManagerRetriever.get() 方法中如果传入的是带有生命周期的组件,并且在 UI 线程,会执行以下几个方法端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// FragmentActivity
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null /*parentHint*/);

//android.support.v4.app.Fragment
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment);

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

//android.app.Fragment
android.app.FragmentManager fm = fragment.getChildFragmentManager();
return fragmentGet(fragment.getActivity(), fm, fragment);
  1. 如果是 Activity ,先获取 FragmentManager ,如果是 Fragment 则先获取 ChildFragmentManager。
  2. 如果是 support 包下面的 Activity 、Fragment 调用 supportFragmentGet,否则调用 fragmentGet。

fragmentGet() 和 supportFragmentGet() 方法大致类似,选取一个分析一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private RequestManager fragmentGet(Context context, android.app.FragmentManager fm,
android.app.Fragment parentHint) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
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;
}

上面这段代码做了两个功能

1
2
1. 创建一个 RequestManagerFragment。
2. 创建一个 RequestManager。

先看一下 getRequestManagerFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(
final android.app.FragmentManager fm, android.app.Fragment parentHint) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}

这是是 Glide 设计中比较一个巧妙的地方

1
2
创建一个透明的 RequestManagerFragment 加入到FragmentManager 之中
通过添加的这个 Fragment 感知 Activity 、Fragment 的生命周期。

在 RequestManagerFragment 中可以看到以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}

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

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

可以通过 RequestManagerFragment 把 Activity 的生命周期通过 lifecycle 传递给在 lifecycle 注册的 LifecycleListener。

RequestManager.load(url)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}

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

public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}

public RequestBuilder<TranscodeType> load(@Nullable Object model) {
return loadGeneric(model);
}

private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}

以上就是 RequestBuilder.load(url) 的相关代码,发现并没有什么特殊之处。 只是创建了一个 RequestBuilder 。

RequestBuilder.into(view)

into() 方法调用起来十分方便,只要传递一个 ImageView ,Glide 就会自动下载图片,并且显示到 ImageView 上。这看似十分简单的一步,也是 Glide 最负责的调用。

1
2
3
4
5
6
7
8
9
10
public Target<TranscodeType> into(ImageView view) {

RequestOptions requestOptions = this.requestOptions;
……

return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}

跟踪一下 glideContext.buildImageViewTarget(view, transcodeClass) 会发现这里返回的是一个DrawableImageViewTarget
into(ImageView view) 把 requestOptions 和 DrawableImageViewTarget 传入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
RequestOptions options) {
……
Request request = buildRequest(target, targetListener, options);

Request previous = target.getRequest();
……
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);

return target;
}

下一步跟踪到 requestManager.track(target, request)

1
2
3
4
5
6
7
8
9
10
11
12
13
 void track(Target<?> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}

public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}

isPaused 变量

1
2
3
4
5
1. 如果此时 GlideRequests 的 Lifecycle 为 ApplicationLifecycle,只要应用存活
isPaused 为 false ,直接执行 request.begin()
2. 如果 GlideRequests 的 Lifecycle 是观测 Fragment 或者 Activity
isPaused 为true ,不会立即执行 request.begin()
当 Fragment 或者 Activity 显示到前台时通过遍历 requests 数组执行 request.begin()

所以执行网络请求下载图片的操作在 request.begin() 之中。
回到 into(ImageView view) 方法的

1
Request request = buildRequest(target, targetListener, options)

经过层层包裹我们可以找到一下路线,发现最后返回的是 SingleRequest

1
2
3
buildRequest >> buildRequestRecursive >> buildThumbnailRequestRecursive

>> obtainRequest >> SingleRequest

创建 SingleRequest 的过程比较复杂,牵扯到缩略图、错误处理之类的逻辑,大致都是上面那条路径。

然后就看一下 SingleRequest.begin()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public void begin() {
……
省略一些其他分支
……
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
……
……
}

begin() 方法很长,我们剔除了一些异常处理,直接看最核心的方法。

如果我给 Glide 设置了 override() 则直接调用 onSizeReady(overrideWidth, overrideHeight)

否则会调用 target.getSize(this) 让 ImageView 计算自己的尺寸。

1
glideContext.buildImageViewTarget(view, transcodeClass) 创建一个 DrawableImageViewTarget

Glide流程

Glide网络下载流程

总结

  • 缓存
    • 活动资源 (Active Resources)
    • 内存缓存 (Memory Cache)
    • 资源类型(Resource Disk Cache)
    • 原始数据 (Data Disk Cache)
    • 网络缓存
希望对您有所帮助,您的支持将是我莫大的动力!