Glide的自问自答

1. Glide的缓存有哪些

内存缓存和磁盘缓存

2. 缓存对应的实现类是什么

内存缓存:

  1. ActiveResource
  2. LruResourceCache
  • ActiveResource是使用HaspMap进行的数据存储.键值是用弱引用进行的包装.为什么要用弱引用,因为他缓存的是正在使用的图片,当页面被销毁了,你还拿着对象的引用,会造成内存泄漏,所以要用弱引用进行包装.
  • LruResourceCache他缓存的是所有曾经加载过的图片信息,他和ActiveResource的区别是,他底层使用了Lru算法,然后Lru算法的实现是通过LinkedHashmap.为什么LruResourceCache要用到Lru算法,然后还不用弱引用.因为他缓存的不是正在使用的图片,不会存在内存泄漏的问题.然后如果他也使用了弱引用,就会导致缓存的资源被频繁的清空,也就失去了缓存的意义了.当然,缓存的大小总是有个边界的,所以使用了Lru算法,在超过缓存大小后删除那些最近最少使用的资源.这个实现就是用到了LinkedHashMap.LinkedHashMap继承HashMap,他重写了newNode方法,键值封装到了LinkedHashMapEntry里面,维护了一个双向链表.这样我们就能得到我们的插入顺序了.新插入的值是插在链表的尾部的.默认情况下LinkedHashMap的插入顺序和遍历顺序是一样的,但是我们通过改变accessOrder值为true

3. 如何全局设置Glide的加载配置,并且他的原理是什么,为什么可以设置一个全局的加载配置

在Glide里,配置信息都是写入BaseRequesOptions里面.我们每次发起请求通过Glide.with(context)先获取当前页面的RequestManager,然后在调用load创建RequestBuilder对象,这个对象是每次调用load都会创建一个新的.我们可以看到RequestBuilder是继承BaseRequestOptions的.看下对象创建的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class RequestManager{
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
}
class RquestBuilder{
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
----
apply(requestManager.getDefaultRequestOptions());
}
}

其他都是浮云.重点是RequestBuilder的构造函数里面的apply方法.

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
public T apply(@NonNull BaseRequestOptions<?> o) {
BaseRequestOptions<?> other = o;

if (isSet(other.fields, SIZE_MULTIPLIER)) {
sizeMultiplier = other.sizeMultiplier;
}
if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) {
useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool;
}
if (isSet(other.fields, USE_ANIMATION_POOL)) {
useAnimationPool = other.useAnimationPool;
}
if (isSet(other.fields, DISK_CACHE_STRATEGY)) {
diskCacheStrategy = other.diskCacheStrategy;
}
if (isSet(other.fields, PRIORITY)) {
priority = other.priority;
}
if (isSet(other.fields, ERROR_PLACEHOLDER)) {
errorPlaceholder = other.errorPlaceholder;
errorId = 0;
fields &= ~ERROR_ID;
}
if (isSet(other.fields, ERROR_ID)) {
errorId = other.errorId;
errorPlaceholder = null;
fields &= ~ERROR_PLACEHOLDER;
}
if (isSet(other.fields, PLACEHOLDER)) {
placeholderDrawable = other.placeholderDrawable;
placeholderId = 0;
fields &= ~PLACEHOLDER_ID;
}
if (isSet(other.fields, PLACEHOLDER_ID)) {
placeholderId = other.placeholderId;
placeholderDrawable = null;
fields &= ~PLACEHOLDER;
}
if (isSet(other.fields, IS_CACHEABLE)) {
isCacheable = other.isCacheable;
}
if (isSet(other.fields, OVERRIDE)) {
overrideWidth = other.overrideWidth;
overrideHeight = other.overrideHeight;
}
if (isSet(other.fields, SIGNATURE)) {
signature = other.signature;
}
if (isSet(other.fields, RESOURCE_CLASS)) {
resourceClass = other.resourceClass;
}
if (isSet(other.fields, FALLBACK)) {
fallbackDrawable = other.fallbackDrawable;
fallbackId = 0;
fields &= ~FALLBACK_ID;
}
if (isSet(other.fields, FALLBACK_ID)) {
fallbackId = other.fallbackId;
fallbackDrawable = null;
fields &= ~FALLBACK;
}
if (isSet(other.fields, THEME)) {
theme = other.theme;
}
if (isSet(other.fields, TRANSFORMATION_ALLOWED)) {
isTransformationAllowed = other.isTransformationAllowed;
}
if (isSet(other.fields, TRANSFORMATION_REQUIRED)) {
isTransformationRequired = other.isTransformationRequired;
}
if (isSet(other.fields, TRANSFORMATION)) {
transformations.putAll(other.transformations);
isScaleOnlyOrNoTransform = other.isScaleOnlyOrNoTransform;
}
if (isSet(other.fields, ONLY_RETRIEVE_FROM_CACHE)) {
onlyRetrieveFromCache = other.onlyRetrieveFromCache;
}

// Applying options with dontTransform() is expected to clear our transformations.
if (!isTransformationAllowed) {
transformations.clear();
fields &= ~TRANSFORMATION;
isTransformationRequired = false;
fields &= ~TRANSFORMATION_REQUIRED;
isScaleOnlyOrNoTransform = true;
}

fields |= other.fields;
options.putAll(other.options);

return selfOrThrowIfLocked();
}

可以看到apply方法就是一个拷贝的操作,他将requestManager.getDefaultRequestOptions()默认配置赋值给了新的RequestBuilder.所以我们可以操作的点出来了.
我们通过修改getDefultRequestoptions就可以实现修改全局的GLide加载属性了. 这里我拿修改Glide的编码格式为DecodeFormat.PREFER_RGB_565来举例.(应用场景:在手机内存太小的手机上,用来减少图片的内存占用).

1
2
3
4
5
6
7
8
9
10
11
12
@GlideModule
class MyGlideModule : AppGlideModule(){
override fun applyOptions(context: Context, builder: GlideBuilder) {
super.applyOptions(context, builder)
val activityManager:ActivityManager = context.getSystemService(Context.ALARM_SERVICE) as ActivityManager
if(activityManager!=null){
var memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
builder.setDefaultRequestOptions(RequestOptions().format(DecodeFormat.PREFER_RGB_565))
}
}
}
1
2
3
<meta-data
android:name="com.adventure.live.MyGlideModule"
android:value="GlideModule" />

实现方法就是继承AppGlideModule重写applyOptions方法.