Glide-设置缓存的key

本文探讨了Glide图片加载库在处理阿里云私有图片时遇到的问题,并提出通过继承GlideUrl类并重写getCacheKey方法来解决缓存失效问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承GildeUrl类
在项目开发中遇到了一个问题:
图片是上传到阿里云上的,因为图片是私有的,图片地址后面会带有一些权限的认证,这样用一张图片地址会经常的变化,这样用gilde默认的缓存基本上失效。
public class Engine implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {

public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();

final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
...
}

...
}
蓝色部分id其实就是图片的url,EnginKey就是glide图片缓存的key。
fetcher源码:
public class HttpUrlFetcher implements DataFetcher<InputStream> {

private final GlideUrl glideUrl;
...
public HttpUrlFetcher(GlideUrl glideUrl) {
this(glideUrl, DEFAULT_CONNECTION_FACTORY);
}
HttpUrlFetcher(GlideUrl glideUrl, HttpUrlConnectionFactory connectionFactory) {
this.glideUrl = glideUrl;
this.connectionFactory = connectionFactory;
}
@Override
public String getId() {
return glideUrl.getCacheKey();
}
...
}
从代码可以看到,getId获取的url其实就是glideUrl的getCacheKey方法返回的。
GlideUrl源码:
public class GlideUrl {

private final URL url;
private final String stringUrl;
...

public GlideUrl(URL url) {
this(url, Headers.DEFAULT);
}

public GlideUrl(String url) {
this(url, Headers.DEFAULT);
}

public GlideUrl(URL url, Headers headers) {
...
this.url = url;
stringUrl = null;
}

public GlideUrl(String url, Headers headers) {
...
this.stringUrl = url;
this.url = null;
}

public String getCacheKey() {
return stringUrl != null ? stringUrl : url.toString();
}

...
}
可以看出getCacheKey方法,如果传入的是字符串,就直接返回,如果是URL就返回toString()。
这样的话就可以继承GlideUrl,重写getCacheKey方法,自己处理要返回的key。
public class MyGlideUrl extends GlideUrl {

private String mUrl;

public MyGlideUrl(String url) {
super(url);
mUrl = url;
}
@Override
public String getCacheKey() {
if(!TextUtils.isEmpty(mUrl)&& mUrl.contains("\\?")){
String[] urlArr = mUrl.split("\\?");
if(urlArr.length > 0){
return urlArr[0];
}
}
return mUrl;
}
}
实际调用方式:
Glide.with(this)
.load(new MyGlideUrl(url))
.into(imageView);

从上面的分析中,发现EngineKey是缓存的key,它的参数有很多,其中有个signature,当我们在项目中,图片url不变,但是缓存的策略不是以url当做key,就可以用到这个signature。GlideUrl提供了对应的方法。
Glide.with(this)
.load(url)
.signature(new StringSignature("id"))
.into(imageView);

这样key就与url和StringSignature设置的字符串有关联了










### Glide 中三级缓存的工作原理 #### 内存缓存 (Memory Cache) 内存缓存Glide中最先被访问的一层缓存。当请求一张图片时,会优先尝试从内存缓存中获取该图片。如果存在,则直接返回给调用者;否则继续向下一层级查找。 为了高效管理有限的内存空间,Glide采用了`LruCache`算法来实现这一层次的缓存机制[^4]。这意味着最近最少使用的条目会被移除以腾出更多可用的空间供新的数据存储使用。 ```java // LRU Cache implementation example public class ImageCache { private final int maxSize; private LinkedHashMap<String, Bitmap> cache; public ImageCache(int maxSize) { this.maxSize = maxSize; this.cache = new LinkedHashMap<>(maxSize / 2, 0.75f, true); } synchronized Bitmap get(String key) { return cache.get(key); } } ``` #### 磁盘缓存 (Disk Cache) 如果未能命中内存缓存,那么接下来就会查询磁盘上的持久化文件作为第二道防线。对于那些已经被下载过但是不在当前活动状态下的资源来说特别有用。它同样遵循LRU原则,并且利用了`DiskLruCache`来进行具体操作。 这种设计使得即使应用程序重启之后仍然可以快速恢复之前已经加载过的图像而无需再次发起网络请求。 ```java // Disk LRU Cache usage pattern File diskCacheDir = context.getExternalCacheDir(); if (!diskCacheDir.exists()) { diskCacheDir.mkdirs(); } final long DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB try { mDiskLruCache = DiskLruCache.open(diskCacheDir, getAppVersion(context), 1, DISK_CACHE_SIZE); } catch (IOException e) { Log.e(TAG, "Failed to create DiskLruCache", e); } ``` #### 源缓存 (Source Cache 或 Network Cache) 最后一级即远程服务器端的数据源本身也可以视为一种形式上的“缓存”。每当上述两种本地缓存均未找到目标对象时便会触发实际HTTP GET动作去拉取最新版本的内容并将其保存下来以便将来重用[^2]。 一旦成功取得新图档后除了立即呈现在界面上之外还会同步更新到前面提到的所有级别当中从而形成完整的闭环处理逻辑链路。 综上所述,在整个过程中涉及到多个组件之间的协作配合共同完成了高效的异步预读取/写入流程优化用户体验的同时也降低了带宽消耗成本。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值