缓存机制与缓存失效
缓存失效是一个比较复杂的话题,理想情况下,你尽可能不要考虑这个问题。这一节主要是让你粗略的了解一下Glide中cache的key是如何生成,以及提供一些关于如何合理利用缓存的提示。
缓存的key
DiskCacheStrategy.RESULT
磁盘缓存策略(注:我们配置的一种磁盘缓存策略)使用的key由以下四个主要部分组成:
- DataFetcher的方法
getId()
返回的字符。典型地,DataFetcher仅仅返回由数据Model的toString()
方法得到的值。所以,如果Model是一个URL,那么会返回URL的字符串,如果Model是是一个文件,那么会返回文件的路径。。。 - 宽和高。如果你调用过override(width,height)方法,那么就是是它传入的值。没有调用过,默认是通过Target的
getSize()
方法获得这个值。 - 各种编码器、解码器的
getId()
方法返回的字符串。这些编码器、解码器用于加载和缓存你的图片。仅有哪些堆bytes数据有影响的编码器、解码器才会有这些id
值。比如,你只有一个将bytes数据写入磁盘的编码器,那么它就没有id值,因为不管怎样它都不会修改数据。 - 可选地,你可以为图片加载提供签名(Signature),请看下面的缓存失效部分。
所有的这些key,以特定的顺序计算出hash值,并将这个值作为保存图片到磁盘上的唯一且安全的文件名。
缓存失效
由于文件名是hash值,没有简便的方式删除磁盘上某个特定url或者文件路径的所有缓存文件。如果仅仅缓存原文件,问题可能还比较简单,但是Glide会缓存缩略图,各种变换后的图片,所有这些缓存都会产生新文件。跟踪和删除所有文件是十分困难的。
自定义缓存失效
通常情况下改变缓存的标志(key)是困难的。Glide提供了signature()
API来混入其他数据,帮助你控制缓存的key。签名(Signature)对于多媒体或者有版本信息的内容来说都很有用。
- 媒体库内容 - 对于媒体库内容,你可以使用Glide的
MediaStoreSignature
类作为签名, MediaStoreSignature类允许你混入文件修改时间、mime类型、媒体库的方向(orientation?)这些值作为缓存的key,这三个值足以让你可靠的捕捉到任何修改和更新,使你可以缓存媒体库的缩略图.? - 文件 - 你可以使用
StringSignature
混入文件修改时间 - url - 虽然使url失效最好的方式是当内容变化时,服务器修改url并更新客户端,但是你也可以用
StringSignature
混入任意的元数据(如版本号)来使缓存失效。
使用String Signature加载数据很简单:
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new StringSignature(yourVersionMetadata))
.into(yourImageView);
媒体库Signature可以直接使用从MeidaStore(注:一个android api)获得的数据
Glide.with(fragment)
.load(mediaStoreUri)
.signature(new MediaStoreSignature(mimeType, dateModified, orientation))
.into(view);
你还可以通过实现key
接口来自定义签名,确保实现了equals()
, hashCode()
和updateDiskCacheKey()
这几个方法
public class IntegerVersionSignature implements Key {
private int currentVersion;
public IntegerVersionSignature(int currentVersion) {
this.currentVersion = currentVersion;
}
@Override
public boolean equals(Object o) {
if (o instanceof IntegerVersionSignature) {
IntegerVersionSignature other = (IntegerVersionSignature) o;
return currentVersion = other.currentVersion;
}
return false;
}
@Override
public int hashCode() {
return currentVersion;
}
@Override
public void updateDiskCacheKey(MessageDigest md) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());
}
}
请牢记:为了避免性能下降,请在后台线程中批量加载版本元数据(metaData,注:一般查询数据库获得),只有这样,才能确保当你想加载图片的时候,这些值是可用的。
如果这些方法都失败了,比如,你不能改变标识符,也不能跟踪一个合理的版本号。你还可以使用diskCacheStrategy()
和DiskCacheStrategy.NONE.
来完全关闭磁盘缓存。