缓存机制与缓存失效

缓存失效是一个比较复杂的话题,理想情况下,你尽可能不要考虑这个问题。这一节主要是让你粗略的了解一下Glide中cache的key是如何生成,以及提供一些关于如何合理利用缓存的提示。

缓存的key

DiskCacheStrategy.RESULT磁盘缓存策略(注:我们配置的一种磁盘缓存策略)使用的key由以下四个主要部分组成:

  • DataFetcher的方法getId()返回的字符。典型地,DataFetcher仅仅返回由数据Model的toString()方法得到的值。所以,如果Model是一个URL,那么会返回URL的字符串,如果Model是是一个文件,那么会返回文件的路径。。。
  • 宽和高。如果你调用过override(width,height)方法,那么就是是它传入的值。没有调用过,默认是通过TargetgetSize()方法获得这个值。
  • 各种编码器、解码器的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.来完全关闭磁盘缓存。