Glide(二)Request队列管理

Posted by Jfson on 2017-10-08

入口

上篇总结了下Glide利用fm和一个空Fragment 进行生命周期的管理,这里继续看load & into。不多说,上代码

1
2
// 上篇分析了with,继续看下 load & into
Glide.with(this).load("url").into(...);
  • 1.1 load
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
// 实例一个RequestBuilder
public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass);
}
// RequestBuilder 构造中的 requestManager
protected RequestBuilder(Glide glide, RequestManager requestManager,
Class<TranscodeType> transcodeClass) {
this.glide = glide;
this.requestManager = requestManager;
this.context = glide.getGlideContext();
this.transcodeClass = transcodeClass;
this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.requestOptions = defaultRequestOptions;
}
  • 2.1 into
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
public Target<TranscodeType> into(ImageView view) {
// 主线程校验(涉及View刷新)
Util.assertMainThread();
// View 非空校验
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// 获取图片位置类型
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(context.buildImageViewTarget(view, transcodeClass), requestOptions);
}
// 继续看into
private <Y extends Target<TranscodeType>> Y into(@NonNull Y target, RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
// 根据target & options中的属性 build 一个 Request
Request request = buildRequest(target, options);
// target 与 request 绑定,这里复用之前的Request
Request previous = target.getRequest();
// 这里校验request 是否一致 previous
//一致就回收掉request
if (request.isEquivalentTo(previous)) {
request.recycle();
//这里的是校验 previous 执行情况。
//begin内部机制:
//如果正在运行,会保证不中断运行
//如果完成则重新开始并提交
//如果失败,重新开始
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
// 如果两个request 不一致,则删除旧的,更新requestManager中的tartget,requesr到set
requestManager.clear(target);
target.setRequest(request);
// requestManager 添加请求到 RequestTracker中 Set<Request>
requestManager.track(target, request);
return target;
}
  • 2.2 上面不难看出新建的request通过requestManager 添加请求到 RequestTracker中,requestManager 维护了一个RequestTracker,可以做到根据生命周期来处理所有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
// 在生命周期回调中,对应targetTracker不同处理
@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();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
  • 3.1 RequestManager中,requestTracker做为RequestManager成员变量被创建和初始化,所有request都由RequestManager加到了requestTracker中来管理,并与生命周期挂钩。看下requestTracker

package com.bumptech.glide.manager;

import com.bumptech.glide.request.Request;
import com.bumptech.glide.util.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;

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
public class RequestTracker {
// 用set 防止未开始或者onPause的时候被GC干掉
private final Set<Request> requests =
Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final List<Request> pendingRequests = new ArrayList<>();
private boolean isPaused;
/**
* Starts tracking the given request.
*/
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
// Visible for testing.
void addRequest(Request request) {
requests.add(request);
}
/**
* Stops tracking the given request, clears, and recycles it, and returns {@code true} if the
* request was removed or {@code false} if the request was not found.
*/
public boolean clearRemoveAndRecycle(Request request) {
if (request == null) {
return false;
}
boolean isOwnedByUs = requests.remove(request);
// Avoid short circuiting.
isOwnedByUs = pendingRequests.remove(request) || isOwnedByUs;
if (isOwnedByUs) {
request.clear();
request.recycle();
}
return isOwnedByUs;
}
/**
* Returns {@code true} if requests are currently paused, and {@code false} otherwise.
*/
public boolean isPaused() {
return isPaused;
}
/**
* Stops any in progress requests.
*/
public void pauseRequests() {
isPaused = true;
for (Request request : Util.getSnapshot(requests)) {
if (request.isRunning()) {
request.pause();
pendingRequests.add(request);
}
}
}
/**
* Starts any not yet completed or failed requests.
*/
public void resumeRequests() {
isPaused = false;
for (Request request : Util.getSnapshot(requests)) {
if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
request.begin();
}
}
pendingRequests.clear();
}
/**
* Cancels all requests and clears their resources.
*
* <p>After this call requests cannot be restarted.
*/
public void clearRequests() {
for (Request request : Util.getSnapshot(requests)) {
clearRemoveAndRecycle(request);
}
pendingRequests.clear();
}
/**
* Restarts failed requests and cancels and restarts in progress requests.
*/
public void restartRequests() {
for (Request request : Util.getSnapshot(requests)) {
if (!request.isComplete() && !request.isCancelled()) {
// Ensure the request will be restarted in onResume.
request.pause();
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
}
}
@Override
public String toString() {
return super.toString() + "{numRequests=" + requests.size() + ", isPaused=" + isPaused + "}";
}
}
  • 3.2 以上看出RequestTracker对所有Requst进行对应生命周期的维护

      1. 比如onPause时,对所有Request暂停,加入set
      1. onResume 时,对所有Request 进行restart
      1. onStop 时,clear all Request
  • 一波666

总结

  • 主要对所有Request 进行队列维护,并在生命周期回调中进行相应优化
  • 梳理了一下,看图比较直接

结构类图


pv UV: