Glide源码剖析-into

本篇将分析源码Glide.into()方法

Glide源码剖析-into

将分析源码Glide.into()

into()

可以发现,前面两个方法with()和load()都没有涉及到图片的请求、缓存、解码等别的逻辑。那么都会在into()里,所以这部分会非常复杂:muscle:加油

1
Glide.with(this).load("图片资源").into(image)

重载方法

into()的重载方法和View的那套差不多,都是向下重复调用重载方法

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
#RequestBuilder
@NonNull
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null, Executors.mainThreadExecutor());
}
---分割---
@NonNull
@Synthetic
<Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
Executor callbackExecutor) {
return into(target, targetListener, /*options=*/ this, callbackExecutor);
}
---分割---
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request request = buildRequest(target, targetListener, options, callbackExecutor);

Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}

requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);

return target;
}

最终会还是会来到

1
2
3
4
into(@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor){}

这个方法,我们一步一步分析

  1. 首先,会判断前面是否调用过load(),因为只有调用了load(),isMolderSet才会为true

    1
    2
    3
    4
    5
    #RequestBuilder
    if (!isModelSet) {
    throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    ...

    保证调用顺序不发生错误

  2. 通过buildeRequest()构建了一个Request

    1
    2
    3
    4
    #RequestBuilder
    ...
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    ...

    那就先继续去看看buildRequest()

buildRequest()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#RequestBuilder
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
/*requestLock=*/ new Object(),
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}

BaseRequestOptions:是之前load()创建RequestBuilder时,调用的apply设置的一些默认参数

transitionOptions:用于设置加载完成时在资源上使用的转换的基类

可以看到它又将参数和一些额外参数都传递进了buildRequestRecursive。到目前为止都还没有看到实际性的构建代码:sweat:,那就只能继续深入

buildRequestRecursive()

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
#RequestBuilder
private Request buildRequestRecursive(
Object requestLock,
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {

// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
// 错误请求协调者
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {// 如果没有设置错误后构建,那么是不会有errorBuilder
errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);// 创建协调
parentCoordinator = errorRequestCoordinator;
}
// 构建主请求
Request mainRequest =
buildThumbnailRequestRecursive(
requestLock,
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
// 如果没有设置errorBuilder,那么就会直接返回mainRequest
if (errorRequestCoordinator == null) {
return mainRequest;
}
// 下面为设置了error时,返回errorRequest
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}

Request errorRequest =
errorBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
//将两个请求都放入协调中
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}

ErrorRequestCoordinator:为协调器,目的是可以让errorRequest和mainRequest一起工作

关于errorBuilder的这行代码,如果没有设置在主请求失败时开始新的请求(如下设置),那么是不会走最后去递归构建错误请求。

1
2
// 设置在主请求失败时开始新的请求
Glide.with(this).load(url).error(Glide.with(this).load(url)).into(imageView);

所以我们先看一下没有设置erro的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#buildRequestRecursive
Request mainRequest =
buildThumbnailRequestRecursive(
requestLock,
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);

if (errorRequestCoordinator == null) {
return mainRequest;
}

可以看到如果没有设置error,那么errorRequestCoordinator一定会为空,所以就到此为止返回一个buildThumbnailRequestRecursive出去。那么继续

buildThumbnailRequestRecursive()

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
#RequestBuilder
private Request buildThumbnailRequestRecursive(
Object requestLock,
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
// 如果没有设置缩略图,那么thumbnailBuilder为空
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
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()");
}

TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;

// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}

Priority thumbPriority =
thumbnailBuilder.isPrioritySet()
? thumbnailBuilder.getPriority()
: getThumbnailPriority(priority);

int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
// 判断是否设置了override
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
// 缩略图协调器
ThumbnailRequestCoordinator coordinator =
new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
// 构建原图
Request fullRequest =
obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
// 构建缩略图
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
requestLock,
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
// 都添加到协调器中去
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
// thumbSizeMultiplier缩放比例,没有设置也是为空
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator =
new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
Request fullRequest =
obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
BaseRequestOptions<?> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

Request thumbnailRequest =
obtainRequest(
requestLock,
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight,
callbackExecutor);

coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// 主请求
return obtainRequest(
requestLock,
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}

“代码很长,你忍耐一下”条主要的分析把:collision:

这里有些地方和上面的error有点类似,比如说一开始就判断thumbnailBuilder 是否为空

thumbnailBuilder 也和error一样,只有设置了缩略图才会不为空

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

thumbSizeMultiplier:不为空,说明设置了缩放比例(如下设置)

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

这里就先不去理分支了,先直接看获取原图。(套不下去了,太深了)可以看到,如果没有设置缩略图和缩略比例,那么就只会调用obtainRequest()

obtainRequest()

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
#RequestBuilder
private Request obtainRequest(
Object requestLock,
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
return SingleRequest.obtain(
context,
glideContext,
requestLock,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
SingleRequest
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
#SingleRequest
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object requestLock,
Object model,
Class<R> transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> requestListeners,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory,
Executor callbackExecutor) {
return new SingleRequest<>(
context,
glideContext,
requestLock,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
engine,
animationFactory,
callbackExecutor);
}
---分割---
private SingleRequest(
Context context,
GlideContext glideContext,
@NonNull Object requestLock,
@Nullable Object model,
Class<R> transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
@Nullable RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> requestListeners,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory,
Executor callbackExecutor) {
// 将传入进来的参数都赋值给成员变量
this.requestLock = requestLock;
this.context = context;
this.glideContext = glideContext;
this.model = model;
this.transcodeClass = transcodeClass;
this.requestOptions = requestOptions;
this.overrideWidth = overrideWidth;
this.overrideHeight = overrideHeight;
this.priority = priority;
this.target = target;
this.targetListener = targetListener;
this.requestListeners = requestListeners;
this.requestCoordinator = requestCoordinator;
this.engine = engine;
this.animationFactory = animationFactory;
this.callbackExecutor = callbackExecutor;
status = Status.PENDING;

if (requestOrigin == null && glideContext.getExperiments().isEnabled(LogRequestOrigins.class)) {
requestOrigin = new RuntimeException("Glide request origin trace");
}
}

泪目,终于到头了:cry:这里也是将参数传递进去,最终构建了一个SingleRequest出来。可是我们一开始不是要的是Request吗?

1
public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback{}

SingleRequest是Request的具体实现

回到开头,现在Request有了,最上面的代码中还有一个地方没处理,那就是track()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#RequestBuilder
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
...
Request request = buildRequest(target, targetListener, options, callbackExecutor);
...
Request previous = target.getRequest();

requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);// 《--这里

return target;
}

track()

1
2
3
4
5
6
7
8
9
10
11
12
13
#RequestManager
@GuardedBy("this")
private final TargetTracker targetTracker = new TargetTracker();

@GuardedBy("this")
private final RequestTracker requestTracker;

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
// 将一个 target 加入 Set 集合中
targetTracker.track(target);

requestTracker.runRequest(request);
}

很明显,就是将传入进来的Target加入到TargetTracker里去,再调用requestTracker.runRequest()来运行Request

TargetTracker

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
public final class TargetTracker implements LifecycleListener {
private final Set<Target<?>> targets =
Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());

public void track(@NonNull Target<?> target) {
targets.add(target);
}

public void untrack(@NonNull Target<?> target) {
targets.remove(target);
}

@Override
public void onStart() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onStart();
}
}

@Override
public void onStop() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onStop();
}
}

@Override
public void onDestroy() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onDestroy();
}
}

@NonNull
public List<Target<?>> getAll() {
return Util.getSnapshot(targets);
}

public void clear() {
targets.clear();
}
}

TargetTracker看起来还是比较简单的,track()就是将Target加入一个Set集合中去,其余的操作都是对Set集合中的数据进行遍历操作

Collections.newSetFromMap():JDK1.6开始提供的,用于将生成的Map包装成Set,这样这个Set和被包装的Map拥有相同的key顺序。简单来说就是你可以使用这个工厂类来包装WeakHashMap来生成一个WeakHashSet,因为没有WeakHashSet这个现成的类可用

RequestTracker

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
public class RequestTracker {
private static final String TAG = "RequestTracker";

private final Set<Request> requests =
Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
// A set of requests that have not completed and are queued to be run again. We use this list to
// maintain hard references to these requests to ensure that they are not garbage collected
// before they start running or while they are paused. See #346.
private final Set<Request> pendingRequests = new HashSet<>();

private boolean isPaused;

/** Starts tracking the given request. */
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
}

RequestTracker.runRequest()也还是蛮简单的,一开始也是将request添加到Set集合里去,之后再判断当前是否处于停止状态,是则清空请求,否则开始请求

我们继续深入一下RequestTracker,查看一下RequestTracker.begin(),由于begin是一个接口,SingleRequest又是Request的具体实现,那我们相当于是去看一下SingleRequest.begin()

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
#SingleRequest
@Override
public void begin() {
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {// 判断图片资源是否为空
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {// 判断是否设置了ovreeide
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}

if (status == Status.RUNNING) {// 判断当前状态是否处于运行状态
throw new IllegalArgumentException("Cannot restart a running request");
}

// If we're restarted after we're complete (usually via something like a notifyDataSetChanged
// that starts an identical request into the same Target or View), we can simply use the
// resource and size we retrieved the last time around and skip obtaining a new size, starting
// a new load etc. This does mean that users who want to restart a load because they expect
// that the view size has changed will need to explicitly clear the View or Target before
// starting the new load.
if (status == Status.COMPLETE) {
onResourceReady(
resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return;
}

// Restarts for requests that are neither complete nor running can be treated as new requests
// and can run again from the beginning.

cookie = GlideTrace.beginSectionAsync(TAG);
status = Status.WAITING_FOR_SIZE;// 等待尺寸状态
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}

if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
}
  1. 先判断CallingCallbacks()是否为空

  2. 再判断加载资源是否为空,空的话则调用加载失败的回调

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #SingleRequest
    if (model == null) {
    // 判断是否设置了override
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    width = overrideWidth;
    height = overrideHeight;
    }
    //如果用户设置了回调Drawables,则只在更详细的日志级别进行日志记录,因为回调Drawables表明用户偶尔期望空模型。
    int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
    onLoadFailed(new GlideException("Received null model"), logLevel);
    return;
    }
    ...
  3. 其次再判断当前的状态,是否在运行中,是否完成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ...
    #SingleRequest
    if (status == Status.RUNNING) {
    throw new IllegalArgumentException("Cannot restart a running request");
    }

    // If we're restarted after we're complete (usually via something like a notifyDataSetChanged
    // that starts an identical request into the same Target or View), we can simply use the
    // resource and size we retrieved the last time around and skip obtaining a new size, starting
    // a new load etc. This does mean that users who want to restart a load because they expect
    // that the view size has changed will need to explicitly clear the View or Target before
    // starting the new load.
    if (status == Status.COMPLETE) {
    //调用资源加载完成
    onResourceReady(
    resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
    return;
    }
    ...
  4. 接下来就是判断是否设置了overrideWidth、overrideHeight

    1
    2
    3
    4
    5
    6
    7
    #SingleRequest
    ...
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    onSizeReady(overrideWidth, overrideHeight);
    } else {
    target.getSize(this);
    }

    这里如果设置了overrideWidth、overrideHeight,则会直接调用onSizeRead(),否则的话,会调用getSize()

    设置override

    1
    2
    // 设置加载图片的宽高为 100x100 px
    Glide.with(this).load(url).override(100,100).into(imageView);

    那就继续看一下getSize()方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #Target
    public interface Target<R> extends LifecycleListener {
    ...
    void getSize(@NonNull SizeReadyCallback cb);
    ...
    }
    ---分割---
    #SizeReadyCallback
    public interface SizeReadyCallback {
    void onSizeReady(int width, int height);
    }

    getSize()内部是通过ViewTreeObserver来监听ImageView的高宽,最终也还是调用onSizeReady()

    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
    #SingleRequest
    @Override
    public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {// 同步锁
    if (IS_VERBOSE_LOGGABLE) {
    logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
    if (status != Status.WAITING_FOR_SIZE) {// 如果状态不是等待,就直接跳出
    return;
    }
    status = Status.RUNNING;// 设置状态

    float sizeMultiplier = requestOptions.getSizeMultiplier();// 从配置信息中获取缩略比例
    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);// 根据缩放比例来获取宽度
    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);// 根据缩放比例来获取高度

    if (IS_VERBOSE_LOGGABLE) {
    logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }
    // 开始加载
    loadStatus =
    engine.load(
    glideContext,
    model,
    requestOptions.getSignature(),
    this.width,
    this.height,
    requestOptions.getResourceClass(),
    transcodeClass,
    priority,
    requestOptions.getDiskCacheStrategy(),
    requestOptions.getTransformations(),
    requestOptions.isTransformationRequired(),
    requestOptions.isScaleOnlyOrNoTransform(),
    requestOptions.getOptions(),
    requestOptions.isMemoryCacheable(),
    requestOptions.getUseUnlimitedSourceGeneratorsPool(),
    requestOptions.getUseAnimationPool(),
    requestOptions.getOnlyRetrieveFromCache(),
    this,
    callbackExecutor);

    // This is a hack that's only useful for testing right now where loads complete synchronously
    // even though under any executor running on any thread but the main thread, the load would
    // have completed asynchronously.
    if (status != Status.RUNNING) {
    loadStatus = null;
    }
    if (IS_VERBOSE_LOGGABLE) {
    logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
    }
    }
    1. 首先将状态设置为运行中

    2. 再根据缩略比例来获取图片高宽

      1
      2
      3
      4
      5
      6
      7
      #onSizeReady
      ...
      // 根据缩略比例获取图片宽高
      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
      ...
    3. 最后调用engine.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
      #onSizeReady
      ...
      loadStatus =
      engine.load(
      glideContext,
      model,
      requestOptions.getSignature(),
      this.width,
      this.height,
      requestOptions.getResourceClass(),
      transcodeClass,
      priority,
      requestOptions.getDiskCacheStrategy(),
      requestOptions.getTransformations(),
      requestOptions.isTransformationRequired(),
      requestOptions.isScaleOnlyOrNoTransform(),
      requestOptions.getOptions(),
      requestOptions.isMemoryCacheable(),
      requestOptions.getUseUnlimitedSourceGeneratorsPool(),
      requestOptions.getUseAnimationPool(),
      requestOptions.getOnlyRetrieveFromCache(),
      this,
      callbackExecutor);
      ...

      这里着重关注engine.load()方法,可以猜测为正在加载的部分

Engine.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
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
#Engine
public <R> LoadStatus load(
GlideContext glideContext,
Object model,// 图片加载资源
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,// 是否使用内存缓存
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,// 回调
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);

EngineResource<?> memoryResource; // 内存资源
synchronized (this) {
// 从内存中获取
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

if (memoryResource == null) {
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}

// Avoid calling back while holding the engine lock, doing so makes it easier for callers to
// deadlock.
cb.onResourceReady(
memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return null;
}

上述代码做了4件事情

  1. 使用参数构建了个EngineKey

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //load
    EngineKey key =
    keyFactory.buildKey(
    model,
    signature,
    width,
    height,
    transformations,
    resourceClass,
    transcodeClass,
    options);
  2. 使用EngineKey去获取缓存中的资源,先从内存中进行获取

    1
    2
    //load
    memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
  3. 如果获取不到,则等待或新开启一个EngineJob

    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
    //load
    if (memoryResource == null) {
    return waitForExistingOrStartNewJob(
    glideContext,
    model,
    signature,
    width,
    height,
    resourceClass,
    transcodeClass,
    priority,
    diskCacheStrategy,
    transformations,
    isTransformationRequired,
    isScaleOnlyOrNoTransform,
    options,
    isMemoryCacheable,
    useUnlimitedSourceExecutorPool,
    useAnimationPool,
    onlyRetrieveFromCache,
    cb,
    callbackExecutor,
    key,
    startTime);
    }
  4. 如果获取成功,则调用加载成功的回调

    1
    2
    3
    4
    //load
    cb.onResourceReady(
    memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
    return null;

接下来先不讲解缓存,先继续将主要流程,缓存将再下面部分再进行讲解

waitForExistingOrStartNewJob

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
#Engine
private final Jobs jobs;

private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor,
EngineKey key,
long startTime) {

EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}

EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);

DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);

jobs.put(key, engineJob);

engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);

if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}

waitForExistingOrStartNewJob()做了6件事情

  1. 从成员变量jobs中获取EngineJob,如果获取不为空,则表示当前有正在执行的EngineJob,给EngineJob添加回调并返回新创建的LoadStatus()加载状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //waitForExistingOrStartNewJob
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {// 获取不为空的话,设置回调
    current.addCallback(cb, callbackExecutor);
    if (VERBOSE_IS_LOGGABLE) {
    logWithTimeAndKey("Added to existing load", startTime, key);
    }//并返回加载状态
    return new LoadStatus(cb, current);
    }
  2. 获取为空的话,则通过EngineJob工厂类来创建EngineJob。该类主要用来管理加载以及当加载完成时通知回调

    1
    2
    3
    4
    5
    6
    7
    8
    //waitForExistingOrStartNewJob
    EngineJob<R> engineJob =
    engineJobFactory.build(
    key,
    isMemoryCacheable,// 是否使用内存缓存
    useUnlimitedSourceExecutorPool,// 是否使用无限制的资源执行池
    useAnimationPool,// 是否使用动画池
    onlyRetrieveFromCache);
  3. 使用DecodeJob工厂类来创建DecodeJob。该类主要负责图片的解码,实现了 Runnable 接口,属于一个任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //waitForExistingOrStartNewJob
    DecodeJob<R> decodeJob =
    decodeJobFactory.build(
    glideContext,
    model,
    key,
    signature,
    width,
    height,
    resourceClass,
    transcodeClass,
    priority,
    diskCacheStrategy,
    transformations,
    isTransformationRequired,
    isScaleOnlyOrNoTransform,
    onlyRetrieveFromCache,
    options,
    engineJob);
  4. 将新创建的EngineJob添加到成员变量jobs中去

    1
    2
    //waitForExistingOrStartNewJob
    jobs.put(key, engineJob);
  5. 给新创建的EngineJob添加上回调并调用start()

    1
    2
    3
    //waitForExistingOrStartNewJob
    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);
  6. 返回加载状态

    1
    2
    3
    4
    5
    //waitForExistingOrStartNewJob
    if (VERBOSE_IS_LOGGABLE) {
    logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);

所以接下来我们需要先关注一下engineJob.start()

1
2
3
4
5
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); executor.execute(decodeJob);
}

上述代码就是将传入进来的DecodeJob放入线程池中去运行

DecodeJob

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
#DecodeJob
public void run() {
// This should be much more fine grained, but since Java's thread pool implementation silently
// swallows all otherwise fatal exceptions, this will at least make it obvious to developers
// that something is failing.
GlideTrace.beginSectionFormat("DecodeJob#run(reason=%s, model=%s)", runReason, model);
// Methods in the try statement can invalidate currentFetcher, so set a local variable here to
// ensure that the fetcher is cleaned up either way.
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (CallbackException e) {
// If a callback not controlled by Glide throws an exception, we should avoid the Glide
// specific debug logic below.
throw e;
} catch (Throwable t) {
// Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
// usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
// are however ensuring that our callbacks are always notified when a load fails. Without this
// notification, uncaught throwables never notify the corresponding callbacks, which can cause
// loads to silently hang forever, a case that's especially bad for users using Futures on
// background threads.
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(
TAG,
"DecodeJob threw unexpectedly" + ", isCancelled: " + isCancelled + ", stage: " + stage,t);
}
// When we're encoding we've already notified our callback and it isn't safe to do so again.
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
if (!isCancelled) {
throw t;
}
throw t;
} finally {
// Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
// close in all cases anyway.
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection();
}
}
  1. 判断是否被取消,如果取消了则调用加载失败

    1
    2
    3
    4
    5
    6
    7
    //run
    ...
    if (isCancelled) {
    notifyFailed();
    return;
    }
    ...
  2. 执行

    1
    2
    3
    4
    //run
    ...
    runWrapped();
    ...

    真正的执行都在runWrapped中

  3. 判断状态码是否解码

    1
    2
    3
    4
    5
    6
    7
    //run
    ...
    if (stage != Stage.ENCODE) {
    throwables.add(t);
    notifyFailed();
    }
    ...

runWrapped()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#DecodeJob
private void runWrapped() {
switch (runReason) {// runReason有默认值,是INITIALIZE,所以一般情况下会直接走第一个分支
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);// 获取资源状态
currentGenerator = getNextGenerator();// 根据资源状态来获取资源处理器
runGenerators();// 开始执行
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}

runReason是有默认值的,默认为INITIALIZE

1
2
3
4
#DecodeJob
DecodeJob<R> init(...){
this.runReason = RunReason.INITIALIZE;
}

接下来将会通过INITIALIZE来获取资源状态

1
2
3
4
//runWrapped
...
stage = getNextStage(Stage.INITIALIZE);// 获取资源状态
...
getNextStage()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#DecodeJob
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()// 判断是否使用内存缓存
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()// 判断是否使用硬盘缓存
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:// 配置了禁用内存与磁盘缓存,getNextStage得到的stage为 SOURCE
// Skip loading from source if the user opted to only retrieve the resource from cache.
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}

首先会因为传递进来的是INITIALIZE,所以会进入第一个分支。内部则会判断是否使用内存缓存,如果使用的话,返回状态Stage.RESOURCE_CACHE。不使用的话,则继续递归传入下一个分支

回到runWrapped(),之后会通过资源状态来获取资源执行器

1
2
3
4
//runWrapped
...
currentGenerator = getNextGenerator();
...
getNextGenerator()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#DecodeJob
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}

如果禁用了内存缓存和硬盘缓存,那么这里的stage会是Stage.SOURCE,则会返回SourceGenerator(),拿到资源执行器之后,就是开始执行了,调用了runGenerators()方法

runGenerators()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#DecodeJob
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled
&& currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();

if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}

// Otherwise a generator started a new load and we expect to be called back in
// onDataFetcherReady.
}

while条件中调用了currentGenerator.startNext(),由这里的currentGeneratorSourceGenerator,所以实际上是在调用SourceGenerator.starNext()

SourceGenerator

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 boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
try {
boolean isDataInCache = cacheData(data);
// If we failed to write the data to cache, the cacheData method will try to decode the
// original data directly instead of going through the disk cache. Since cacheData has
// already called our callback at this point, there's nothing more to do but return.
if (!isDataInCache) {
return true;
}
// If we were able to write the data to cache successfully, we now need to proceed to call
// the sourceCacheGenerator below to load the data from cache.
} catch (IOException e) {
// An IOException means we weren't able to write data to cache or we weren't able to rewind
// it after a disk cache write failed. In either case we can just move on and try the next
// fetch below.
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to properly rewind or write data to cache", e);
}
}
}

if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;

loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
// 通过hepler.getLoadData()来获取LoadData集合,然后再通过索引来获取对应的loadData
loadData = helper.getLoadData().get(loadDataListIndex++);
// 判空
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 开始加载
startNextLoad(loadData);
}
}
return started;
}

这里先是使用了helper.getLoadData.get()来获取loadData,再进行判空,如果不为空的话,则调用startNextLoad()

helper.getLoadData.get()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#DecodeHelper
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
// 通过 ModelLoader 对象的 buildLoadData() 方法获取的 LoadData
// 从网络加载数据,这里实际调用的是 com.bumptech.glide.load.model.stream HttpGlideUrlLoader#buildLoadData()
LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
  1. 先通过成员变量modelLoaders,获取一个ModelLoader出来

  2. 再调用buildLoadData来构建一个LoadData

    buildLoadData是一个接口,由于我们当前的是SourceGenerator,也就是只是网络加载,所以这里的buildLoadData实际上是HttpGlideUrlLoader.buildLoadData()

HttpGlideUrlLoader.buildLoadData()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#HttpGlideUrlLoader
public LoadData<InputStream> buildLoadData(
@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
// spent parsing urls.
GlideUrl url = model;// 将图片资源赋值给局部变量
if (modelCache != null) {// 如果modelCache不为空,则将值获取出来
url = modelCache.get(model, 0, 0);
if (url == null) {// 如果获取出来为空,则表示第一次添加,将添加到modelCache中去
modelCache.put(model, 0, 0, model);
url = model;
}
}
int timeout = options.get(TIMEOUT);
// 实例化 LoadData 的时候顺带实例化了 HttpUrlFetcher
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}

startNextLoad

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#SourceGenerator
private void startNextLoad(final LoadData<?> toStart) {
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback<Object>() {
@Override
public void onDataReady(@Nullable Object data) {
if (isCurrentRequest(toStart)) {
onDataReadyInternal(toStart, data);
}
}

@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
  1. loadData.fetcher其实就是刚刚返回LoadData的时候顺便实例化的HttpUrlFetcher

    1
    2
    3
    4
    # interface ModelLoader
    public LoadData(@NonNull Key sourceKey, @NonNull DataFetcher<Data> fetcher) {
    this(sourceKey, Collections.<Key>emptyList(), fetcher);
    }

    所以这里是调用HttpUrlFetcher.loadData()

HttpUrlFetcher.loadData()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void loadData(
@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
// 通过重定向加载数据
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
// 加载成功,将结果通过回调传递给上层的currentGenerator,也就是SourceGenerator
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}

HttpUrlFetcher.loadData()中,要关注两个方法,一个是loadDataWithRedirects(),另一个则是callback.onDataReady()

  • loadDataWithRedirects()

    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
    #HttpUrlFetcher
    private HttpURLConnection urlConnection;

    private InputStream stream;

    private InputStream loadDataWithRedirects(
    URL url, int redirects, URL lastUrl, Map<String, String> headers) throws HttpException {
    if (redirects >= MAXIMUM_REDIRECTS) {
    throw new HttpException(
    "Too many (> " + MAXIMUM_REDIRECTS + ") redirects!", INVALID_STATUS_CODE);
    } else {
    // Comparing the URLs using .equals performs additional network I/O and is generally broken.
    // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
    try {
    if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
    throw new HttpException("In re-direct loop", INVALID_STATUS_CODE);
    }
    } catch (URISyntaxException e) {
    // Do nothing, this is best effort.
    }
    }
    // 将url和头部信息一起构建一个HttpURLConnection
    urlConnection = buildAndConfigureConnection(url, headers);

    try {
    // 明确连接以避免连接失败时解码器出现错误。
    // 发起连接
    urlConnection.connect();
    // 获取输入流
    stream = urlConnection.getInputStream();
    } catch (IOException e) {
    throw new HttpException(
    "Failed to connect or obtain data", getHttpStatusCodeOrInvalid(urlConnection), e);
    }

    if (isCancelled) {
    return null;
    }
    // 获取请求状态码
    final int statusCode = getHttpStatusCodeOrInvalid(urlConnection);
    if (isHttpOk(statusCode)) {// 判断是否请求成功
    return getStreamForSuccessfulRequest(urlConnection);// 获取 InputStream
    } else if (isHttpRedirect(statusCode)) {
    String redirectUrlString = urlConnection.getHeaderField(REDIRECT_HEADER_FIELD);// 估计是获取失败信息
    if (TextUtils.isEmpty(redirectUrlString)) {
    throw new HttpException("Received empty or null redirect url", statusCode);
    }
    URL redirectUrl;
    try {
    redirectUrl = new URL(url, redirectUrlString);
    } catch (MalformedURLException e) {
    throw new HttpException("Bad redirect url: " + redirectUrlString, statusCode, e);
    }
    // 特别需要关闭流以避免额外泄漏responsebody
    // 断开下面的url连接
    cleanup();
    // 继续递归调用
    return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
    throw new HttpException(statusCode);
    } else {
    try {
    throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    } catch (IOException e) {
    throw new HttpException("Failed to get a response message", statusCode, e);
    }
    }
    }

    可以看到Glide内部是选用了HttpURLConnection来进行网络请求的,请求成功之后返回了InputStream

  • callback.onDataReady()

    callback.onDataReady则是将结果返回给currentGenerator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #SourceGenerator
    private void startNextLoad(final LoadData<?> toStart) {
    loadData.fetcher.loadData(
    helper.getPriority(),
    new DataCallback<Object>() {// 《--这里
    @Override
    public void onDataReady(@Nullable Object data) {
    if (isCurrentRequest(toStart)) {
    onDataReadyInternal(toStart, data);
    }
    }

    @Override
    public void onLoadFailed(@NonNull Exception e) {
    if (isCurrentRequest(toStart)) {
    onLoadFailedInternal(toStart, e);
    }
    }
    });
    }

我们继续顺着下去,去看一下onDataReadyInternal()

onDataReadyInternal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#SourceGenerator
private final FetcherReadyCallback cb;

@Synthetic
void onDataReadyInternal(LoadData<?> loadData, Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
// We might be being called back on someone else's thread. Before doing anything, we should
// reschedule to get back onto Glide's thread.
cb.reschedule();
} else {
cb.onDataFetcherReady(
loadData.sourceKey,
data,
loadData.fetcher,
loadData.fetcher.getDataSource(),
originalKey);
}
}

一开始还是一如既往的进行判空和一些别的判断,之后就是调用了FetcherReadyCallback.onDataFetcherReady

FetcherReadyCallback是个接口,只有SourceGenerator和DecodeJob实现了。所以这里实际上是调用DecodeJob.onDataFetcherReady()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#DecodeJob
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey;
this.currentData = data;
this.currentFetcher = fetcher;
this.currentDataSource = dataSource;
this.currentAttemptingKey = attemptedKey;
this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);
// 判断当前线程是否是指定的线程
if (Thread.currentThread() != currentThread) {
// 我们在一个不属于我们的线程上检索了一些数据,并希望切换回我们的线程来处理这些数据。
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
// 开始解码
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}

重点注意decodeFromRetrievedData(),经过了这么多的跳转,终于要开始解码了

decodeFromRetrievedData()

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
#DecodeJob
private DataFetcher<?> currentFetcher;

private Object currentData;

private DataSource currentDataSource;

private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {// 输出日志信息
logWithTimeAndKey(
"Retrieved data",
startFetchTime,
"data: "
+ currentData
+ ", cache key: "
+ currentSourceKey
+ ", fetcher: "
+ currentFetcher);
}
Resource<R> resource = null;
try {
// 开始解码
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);
} else {
runGenerators();
}
}

别的我们都先不管了,先把主流程走一遍,这里有两个地方需要注意,decodeFromData(解码)、notifyEncodeAndRelease(解码完毕,进行通知)

decodeFromData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#DecodeJob
private <Data> Resource<R> decodeFromData(
DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
// 继续调用decodeFromFetcher
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
decodeFromFetcher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#DecodeJob
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
// 获取解码器,解码器里面封装了 DecodePath,它就是用来解码转码的
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
// 通过解码器解析数据
return runLoadPath(data, dataSource, path);
}
---分割---
private <Data, ResourceType> Resource<R> runLoadPath(
Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path)
throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
// 这里相当于是创建了个任务的传送带
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
// 最后还是将任务传递给了path.load()
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}

最终还是将任务传递给了path.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#LoadPath
public Resource<Transcode> load(
DataRewinder<Data> rewinder,
@NonNull Options options,
int width,
int height,
DecodePath.DecodeCallback<ResourceType> decodeCallback)
throws GlideException {
// 从池中取出最后一个实例出来并进行判空异常处理
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
// 最后将这些实例都释放掉
listPool.release(throwables);
}
}
---分割---
private Resource<Transcode> loadWithExceptionList(
DataRewinder<Data> rewinder,
@NonNull Options options,
int width,
int height,
DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions)
throws GlideException {
Resource<Transcode> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}

if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}

return result;
}

这里是将解码的任务交给了Decode Path来完成,所以DecodePath.decode()才是真正开始解析数据的

DecodePath
1
2
3
4
5
6
7
8
9
10
11
12
#DecodePath
public Resource<Transcode> decode(
DataRewinder<DataType> rewinder,
int width,
int height,
@NonNull Options options,
DecodeCallback<ResourceType> callback)
throws GlideException {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
  1. 将图片资源进行解码成原始图片

    1
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);

    decodeResource

    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
    #DecodePath
    @NonNull
    private Resource<ResourceType> decodeResource(
    DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options)
    throws GlideException {
    List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
    try {
    return decodeResourceWithList(rewinder, width, height, options, exceptions);
    } finally {
    listPool.release(exceptions);
    }
    }
    ------------
    @NonNull
    private Resource<ResourceType> decodeResourceWithList(
    DataRewinder<DataType> rewinder,
    int width,
    int height,
    @NonNull Options options,
    List<Throwable> exceptions)
    throws GlideException {
    Resource<ResourceType> result = null;
    //noinspection ForLoopReplaceableByForEach to improve perf
    for (int i = 0, size = decoders.size(); i < size; i++) {
    // 获取当前的资源解码器
    ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
    try {
    DataType data = rewinder.rewindAndGet();
    if (decoder.handles(data, options)) {
    data = rewinder.rewindAndGet();
    // 再调用对应的解码器来进行解码
    result = decoder.decode(data, width, height, options);
    }
    // Some decoders throw unexpectedly. If they do, we shouldn't fail the entire load path, but
    // instead log and continue. See #2406 for an example.
    } catch (IOException | RuntimeException | OutOfMemoryError e) {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    Log.v(TAG, "Failed to decode data for " + decoder, e);
    }
    exceptions.add(e);
    }

    if (result != null) {
    break;
    }
    }

    if (result == null) {
    throw new GlideException(failureMessage, new ArrayList<>(exceptions));
    }
    return result;
    }

    可以看到,这里遍历拿到可以解码当前数据的资源解码器,然后调用 decode() 方法进行解码。

    因为当前数据是 Input Stream,所以这里遍历拿到的 Resource Decoder 其实是 StreamBitmapDecoder,所以调用的是 StreamBitmapDecoder.decode()StreamBitmapDecoder的内部是调用Downsampler.decode()将输入流解码变成Bitmap,最后将Bitmap包装成Resource返回

  2. 将原始图片通过回调通知Decode Job

    回调最终会回到DecodeJob.onResourceDecoded()

    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
    <Z> Resource<Z> onResourceDecoded(DataSource dataSource, @NonNull Resource<Z> decoded) {
    @SuppressWarnings("unchecked")
    Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
    Transformation<Z> appliedTransformation = null;
    Resource<Z> transformed = decoded;
    // 这里判断资源是否是从硬盘中获取的,如果不是则需要进行转换
    if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
    appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
    transformed = appliedTransformation.transform(glideContext, decoded, width, height);
    }
    // TODO: Make this the responsibility of the Transformation.
    if (!decoded.equals(transformed)) {
    decoded.recycle();
    }

    final EncodeStrategy encodeStrategy;
    final ResourceEncoder<Z> encoder;
    if (decodeHelper.isResourceEncoderAvailable(transformed)) {
    encoder = decodeHelper.getResultEncoder(transformed);
    encodeStrategy = encoder.getEncodeStrategy(options);
    } else {
    encoder = null;
    encodeStrategy = EncodeStrategy.NONE;
    }
    // 缓存相关
    Resource<Z> result = transformed;
    boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
    if (diskCacheStrategy.isResourceCacheable(
    isFromAlternateCacheKey, dataSource, encodeStrategy)) {
    if (encoder == null) {
    throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
    }
    final Key key;
    switch (encodeStrategy) {
    case SOURCE:
    key = new DataCacheKey(currentSourceKey, signature);
    break;
    case TRANSFORMED:
    key =
    new ResourceCacheKey(
    decodeHelper.getArrayPool(),
    currentSourceKey,
    signature,
    width,
    height,
    appliedTransformation,
    resourceSubClass,
    options);
    break;
    default:
    throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
    }

    LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
    deferredEncodeManager.init(key, encoder, lockedResult);
    result = lockedResult;
    }
    return result;
    }

    这里是进行资源转换的,也就是如果我们设置了center Crop之类的,那么就会进行对应的转换,最后将结果返回出去

  3. 调用 BitmapDrawableTranscoder.transcode()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public Resource<BitmapDrawable> transcode(
    @NonNull Resource<Bitmap> toTranscode, @NonNull Options options) {
    return LazyBitmapDrawableResource.obtain(resources, toTranscode);
    }
    ---------
    @Nullable
    public static Resource<BitmapDrawable> obtain(
    @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
    if (bitmapResource == null) {
    return null;
    }
    return new LazyBitmapDrawableResource(resources, bitmapResource);
    }
    ---------
    private LazyBitmapDrawableResource(
    @NonNull Resources resources, @NonNull Resource<Bitmap> bitmapResource) {
    this.resources = Preconditions.checkNotNull(resources);
    this.bitmapResource = Preconditions.checkNotNull(bitmapResource);
    }

    这里就是将传入进来的Bitmap封装再Resource里面,顺便再进行一下判空处理

notifyEncodeAndRelease

解码部分完成了,剩下就是要将结果通知出去

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
private void notifyEncodeAndRelease(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease");
try {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}

Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
// 通知完成
notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);

stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// Call onEncodeComplete outside the finally block so that it's not called if the encode
// process
// throws.
// 释放各种资源
onEncodeComplete();
} finally {
GlideTrace.endSection();
}
}

这里通过notifyComplete()进一步的将结果通知给外部,notifyComlete内部使用通过callback.onResourceReady()来进行回调

1
2
3
4
5
6
7
#DecodeJob
private void notifyComplete(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
setNotifiedOrThrow();
// 通知结果回调
callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
}

而实现了callback的只有Engine Job一个,所以这里是将结果返回给了Engine Job

EnginJob

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

@Override
public void onResourceReady(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
this.isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey;
}
// 通知结果回调
notifyCallbacksOfResult();
}

@Synthetic
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
// 如果取消,则回收和释放资源
if (isCancelled) {
resource.recycle();
release();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
} else if (hasResource) {
throw new IllegalStateException("Already have resource");
}
engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);

hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);

localKey = key;
localResource = engineResource;
}

//这里表示 EngineJob 完成了,回调给 Engine
engineJobListener.onEngineJobComplete(this, localKey, localResource);

//遍历 copy 后拿到了线程池的执行器(entry.executor)
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}

这里有两个重要部分,第一个是engineJobListener.onEngineJobComplete()、第二个为entry.executor.execute()

  • engineJobListener.onEngineJobComplete()

    内部主要判断是否配置了内存缓存,如果有,则进行内存缓存

  • entry.executor.execute()

    这里的executor其实就是最上方的传入进来的Executors.mainThreadExecutor()

    1
    2
    3
    4
    5
    #RequestBuilder
    @NonNull
    public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    return into(target, /*targetListener=*/ null, Executors.mainThreadExecutor());
    }

    Executors

    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
    public final class Executors {
    private Executors() {
    // Utility class.
    }

    private static final Executor MAIN_THREAD_EXECUTOR =
    new Executor() {
    @Override
    public void execute(@NonNull Runnable command) {
    Util.postOnUiThread(command);
    }
    };
    private static final Executor DIRECT_EXECUTOR =
    new Executor() {
    @Override
    public void execute(@NonNull Runnable command) {
    command.run();
    }
    };

    /** Posts executions to the main thread. */
    public static Executor mainThreadExecutor() {
    return MAIN_THREAD_EXECUTOR;
    }

    /** Immediately calls {@link Runnable#run()} on the current thread. */
    public static Executor directExecutor() {
    return DIRECT_EXECUTOR;
    }

    @VisibleForTesting
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
    long shutdownSeconds = 5;
    pool.shutdownNow();
    try {
    if (!pool.awaitTermination(shutdownSeconds, TimeUnit.SECONDS)) {
    pool.shutdownNow();
    if (!pool.awaitTermination(shutdownSeconds, TimeUnit.SECONDS)) {
    throw new RuntimeException("Failed to shutdown");
    }
    }
    } catch (InterruptedException ie) {
    pool.shutdownNow();
    Thread.currentThread().interrupt();
    throw new RuntimeException(ie);
    }
    }
    }

    Executors.mainThreadExecutor()其实就是创建了个Executors实例,然后内部重写了execute()方法,还是使用Handler来post一个一个任务并切换到了主线程,所以现在只用去查看CallResourceReady.run()即可

    CallResourceReady

    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
    #EngineJob
    private class CallResourceReady implements Runnable {

    private final ResourceCallback cb;

    CallResourceReady(ResourceCallback cb) {
    this.cb = cb;
    }

    @Override
    public void run() {
    synchronized (cb.getLock()) {
    synchronized (EngineJob.this) {
    if (cbs.contains(cb)) {
    // Acquire for this particular callback.
    engineResource.acquire();
    callCallbackOnResourceReady(cb);
    removeCallback(cb);
    }
    decrementPendingCallbacks();
    }
    }
    }
    }


    void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
    // 资源准备完成后,还是通过回调,传递给上一层
    cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
    throw new CallbackException(t);
    }
    }

这里的cb.onResourceReady()是直接回调给了SingleRequest.onResourceReady()SingleRequest.onResourceReady()内部主要是处理一些加载失败的判断,然后调用重载方法

1
2
3
4
//onResourceReady()
onResourceReady(
(Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
}

onResourceReady

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
private void onResourceReady(
Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;

if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d( GLIDE_TAG, "...“);
}

isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);

if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
// 这里的target是ImageViewTarget,所以这里是直接回调给ImageViewTarget
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
// 通知加载成功
notifyLoadSuccess();
}

最后再ImageViewTarget.onResourceReady()内部会判断传入的animation是否为空,为空的话就会直接设置图片。不为空的话,则会调用animation

animation为空

1
2
3
4
5
6
7
8
9
10
11
12
13
#ImageViewTarget
private void setResourceInternal(@Nullable Z resource) {
// Order matters here. Set the resource first to make sure that the Drawable has a valid and
// non-null Callback before starting it.
setResource(resource);
maybeUpdateAnimatable(resource);
}
---------
#BitmapImageViewTarget
@Override
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}

最终将图片设置到Image View上去

animation不为空

1
2
3
4
5
6
7
8
9
#ImageViewTarget
private void maybeUpdateAnimatable(@Nullable Z resource) {
if (resource instanceof Animatable) {
animatable = (Animatable) resource;
animatable.start();
} else {
animatable = null;
}
}

总结

into()方法十分复杂,主要就是先从内存中进行获取,没有的话,再去硬盘中获取,都没有则通过HttpURLconnection来进行网络请求,其次在将结果给Decode Path进行解码,解码完成将结果封装成Resource通过回调层层传递,中间顺便判断是否需要缓存到硬盘、内存、是否需要进行形状变化。最终将结果设置到Image View上去