Ahab's Studio.

Glide 源码分析 - 请求优先级及原理

字数统计: 695阅读时长: 3 min
2019/02/17 Share

若一个界面中需要展示多张图片,我们可能会期望某张图片优先加载,这就需要设置 Glide 的请求优先级, Glide 中提供四种优先级:

  • Priority.LOW
  • Priority.NORMAL
  • Priority.HIGH
  • Priority.IMMEDIATE

使用十分简单:

1
2
RequestOptions options = new RequestOptions().priority(Priority.HIGH);
Glide.with(context).load(imgUrl).apply(options).into(imageView);

下面来分析一下我们配置的 Priority.HIGH 到底是如何生效的,跟踪发现优先级参数 priority 会被传入到 RequestBuilder 的 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
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
if (thumbnailBuilder != null) {
// 缩略图相关,先忽略
} else if (thumbSizeMultiplier != null) {
// 缩略图相关,先忽略
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
}
}

由于并未设置 thumbnail,先忽略缩略图相关逻辑,此方法中会调用到 obtainRequest 方法,继续跟踪,发现我们配置的 priority 参数在 SingleRequest 中的 onSizeReady 方法中被传入到 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
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) {

// ...省略其他逻辑

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);
engineJob.start(decodeJob);

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

这里在构建 DecodeJob 时将优先级配置传入,最终传入到 DecodeJob 和 DecodeHelper 中,其中 DecodeHelper 被 DecodeJob 持有。

接下来分析 priority 参数分别在什么时候被用到,首先看 DecodeJob 中持有的 priority,其仅在实现 Comparable 接口时用到,这个比较容易理解,可以通过对 DecodeJob 排序来实现优先级的调整。DecodeHelper 中持有的 priority 在 DataFetcher 的 loadData 方法中被传入:

1
void loadData(@NonNull Priority priority, @NonNull DataCallback<? super T> callback);

DataFetch 用于加载数据,其实现有很多:

但并不是所有方法都能应用优先级的,这取决与具体的业务组件,比如 OkHttp 不支持请求优先级设置,直接忽略了 priority 参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public void loadData(@NonNull Priority priority,
@NonNull final DataCallback<? super InputStream> callback) {
Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
String key = headerEntry.getKey();
requestBuilder.addHeader(key, headerEntry.getValue());
}
Request request = requestBuilder.build();
this.callback = callback;

call = client.newCall(request);
call.enqueue(this);
}

而 Volley 就支持请求优先级:

1
2
3
4
5
6
7
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
request = requestFactory.create(url.toStringUrl(), callback, glideToVolleyPriority(priority),
url.getHeaders());
requestQueue.add(request);
}

由此也可以得出设置请求优先级并不是必然生效的。

关注公众号,Get 更多知识点

原文作者:Ahab

原文链接:http://yhaowa.gitee.io/aeb1195c/

发表日期:February 17th 2019, 4:24:53 pm

更新日期:April 7th 2020, 11:34:42 pm

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

CATALOG