android glide面试题,Glide

[Glide 源码分析解读-缓存模块-基于最新版Glide 4.9.0](https://www.jianshu.com/p/62b7f990ee83)

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200307232701.png)

Glide 内部是使用 LruCache、弱引用和硬盘缓存实现的。

Glide 主要将缓存分为两块内存缓存和硬盘缓存,两种缓存的结合,构成了 Glide 缓存机制的核心。

### 内存缓存

~~~

skipMemoryCache(true)

~~~

默认是开始缓存的,如果我们不需要缓存,传入 false

内存缓存会先调用 loadFromCache 方法获取缓存,如果获取到,就直接调用 cb.onResourceReady() 方法进行回调,如果是没获取到,那么往下执行。

~~~

private EngineResource> getEngineResourceFromCache(Key key) {

Resource> cached = cache.remove(key);

final EngineResource result;

if (cached == null) {

result = null;

} else if (cached instanceof EngineResource) {

result = (EngineResource) cached;

} else {

result = new EngineResource(cached, true /*isCacheable*/);

}

return result;

}

~~~

然后会调用 loadFromActiveResources() 方法获取缓存,这个是弱引用实现的,获取到的话也直接进行回调

~~~

private EngineResource> loadFromActiveResources(Key key, boolean isMemoryCacheable) {

if (!isMemoryCacheable) {

return null;

}

EngineResource> active = null;

WeakReference> activeRef = activeResources.get(key);

if (activeRef != null) {

active = activeRef.get();

if (active != null) {

active.acquire();

} else {

activeResources.remove(key);

}

}

return active;

}

~~~

如果两种都获取不到,就会开启新线程去从硬盘或者网路去加载图片。

如果我们在loadFromCache 缓存中找到了缓存,那么会将它从缓存中移除,然后将这个图片添加到 activeResources 中,activeResources 就是一个弱引用的 HashMap,用来缓存正在使用中的图片, loadFromActiveResources 就是从activeResources这个 hashmap 中取值的,这个 activeResources 就是缓存的正在使用的图片,可以保证这些图片不被 LruCache 算法回收掉。

当图片加载完成以后,会将图片加入到 activeResources 中。

在 Glide 内部有个 EngineResource 类中,一个 acquired ,记录图片是不是正在使用,如果等于 0 的时候,就代表没有使用,那么就会从 activityResource 中移除,然后添加到 LruCache 中。

以上就实现了正在使用的图片保存在 弱引用 activeResources中,而内存缓存的图片则保存在 LruCache中。

### 硬盘缓存

~~~

diskCacheStrategy(DiskCacheStrategy.NONE)

~~~

1. DiskCacheStrategy.NONE: 表示不缓存任何内容。

2. DiskCacheStrategy.SOURCE: 表示只缓存原始图片。

3. DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。

4. DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。

### 当图片没变,但是 图片的链接一直在变的时候,怎么缓存?

比如使用七牛云的时候,会在图片url地址的基础之上再加上一个token参数。也就是说,一张图片的url地址可能会是如下格式:

~~~

http://url.com/image.jpg?token=d9caa6e02c990b0a

~~~

而使用Glide加载这张图片的话,也就会使用这个url地址来组成缓存Key。

但是接下来问题就来了,token作为一个验证身份的参数并不是一成不变的,很有可能时时刻刻都在变化。而如果token变了,那么图片的url也就跟着变了,图片url变了,缓存Key也就跟着变了。结果就造成了,明明是同一张图片,就因为token不断在改变,导致Glide的缓存功能完全失效了。

解决办法就是重写 GlideUrl 的 getCacheKey() 方法,把会变的一部分的值给干掉,就可以解决问题。

~~~

public class MyGlideUrl extends GlideUrl {

private String mUrl;

public MyGlideUrl(String url) {

super(url);

mUrl = url;

}

@Override

public String getCacheKey() {

return mUrl.replace(findTokenParam(), "");

}

private String findTokenParam() {

String tokenParam = "";

int tokenKeyIndex = mUrl.indexOf("?token=") >= 0 ? mUrl.indexOf("?token=") : mUrl.indexOf("&token=");

if (tokenKeyIndex != -1) {

int nextAndIndex = mUrl.indexOf("&", tokenKeyIndex + 1);

if (nextAndIndex != -1) {

tokenParam = mUrl.substring(tokenKeyIndex + 1, nextAndIndex + 1);

} else {

tokenParam = mUrl.substring(tokenKeyIndex);

}

}

return tokenParam;

}

}

//使用

Glide.with(this)

.load(new MyGlideUrl(url))

.into(imageView);

~~~

我们需要在load()方法中传入这个自定义的MyGlideUrl对象,而不能再像之前那样直接传入url字符串了。不然的话Glide在内部还是会使用原始的GlideUrl类,而不是我们自定义的MyGlideUrl类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值