【问题标题】:Glide : How to find if the image is already cached and use the cached version?Glide:如何查找图像是否已经缓存并使用缓存版本?
【发布时间】:2015-12-01 02:38:22
【问题描述】:

场景

我有一个大的 GIF 图像,我想在用户第一次使用 Glide - 图像加载和缓存库打开应用程序时对其进行缓存。之后,每当用户打开应用程序时,我想显示缓存版本(如果存在)。此 GIF URL 将在给定时间间隔后过期。当它过期时,我会获取新的 GIF URL 并显示/缓存以供将来使用。

我尝试了什么:

我在 Glide 的 github 页面上浏览了 Caching and Cache Invalidation。我还浏览了 Google Group 线程 Ensuring That Images Loaded Only Come From Disk Cache,它显示了如何获取图像表单缓存。我也经历了How to invalidate Glide cache for some specific images的问题。

从上面的链接中,我看到了以下代码片段,它显示了如何从缓存中加载图像。然而,这只试图从缓存中获取图像。如果它不存在于缓存中,它不会尝试从网络中获取并失败:

Glide.with(TheActivity.this)
        .using(new StreamModelLoader<String>() {
            @Override
            public DataFetcher<InputStream> getResourceFetcher(final String model, int i, int i1) {
                return new DataFetcher<InputStream>() {
                    @Override
                    public InputStream loadData(Priority priority) throws Exception {
                        throw new IOException();
                    }

                    @Override
                    public void cleanup() {
                    }

                    @Override
                    public String getId() {
                        return model;
                    }

                    @Override
                    public void cancel() {
                    }
                };
            }
        })
       .load("http://sampleurl.com/sample.gif")
       .diskCacheStrategy(DiskCacheStrategy.SOURCE)
       .into(theImageView);

问题:

  1. 是否有更简洁的方法来实现以下目标:如果存在,则从缓存中显示 GIF 图像,否则下载 GIF,将其缓存以供以后使用并在 ImageView 中显示。

    李>
  2. 上面的缓存文章提到了以下内容:

    实际上,使缓存文件无效的最佳方法是更改 内容更改时的标识符(url、uri、文件路径等)

    当前一个 URL 过期时,服务器会向应用发送不同的 URL。在这种情况下,我相信旧图像最终会被垃圾收集?有没有办法强制从缓存中删除图像?

  3. 在类似的说明中,有没有办法阻止具有特定键的图像的垃圾收集(以防止再次下载大文件),然后在 URL 更改时指示从缓存中删除旧图像?

【问题讨论】:

    标签: android image-caching android-glide


    【解决方案1】:
    1. 您不需要自定义 ModelLoader 来显示缓存中的 GIF(如果存在)并获取它,这实际上是 Glide 的默认行为。只需使用标准负载线就可以了:

      Glide.with(TheActivity.this)
         .load("http://sampleurl.com/sample.gif")
         .diskCacheStrategy(DiskCacheStrategy.SOURCE)
         .into(theImageView);
      

    您的代码将阻止 Glide 下载 GIF,并且仅在已缓存的情况下才显示 GIF,这听起来像是您不想要的。

    1. 是的,旧图像最终将被删除。默认情况下,Glide 使用 LRU 缓存,因此当缓存已满时,最近最少使用的图像将被删除。如果需要,您可以轻松自定义缓存的大小以帮助实现这一点。请参阅Configuration wiki 页面了解如何更改缓存大小。

    2. 不幸的是,没有任何方法可以直接影响缓存的内容。您既不能显式删除一项,也不能强制保留一项。在实践中,使用适当的磁盘缓存大小,您通常不需要担心这样做。如果您足够频繁地显示您的图像,它就不会被驱逐。如果您尝试缓存其他项目并用完缓存中的空间,则会自动驱逐较旧的项目以腾出空间。

    【讨论】:

    • 非常感谢您花时间回答。实际上,这确实清楚了很多事情。对于你的第一点,这是我想做的事情。我只是不确定这是否是默认行为。然而,让我认为标准代码没有使用缓存图像的原因是,当这段代码第一次执行时,我假设 Glide 缓存了图像。现在我关闭应用程序并关闭互联网。现在,当我打开应用程序时,设备离线时图像不会显示。但是,当我使用问题中提到的StreamModelLoader 时,它会显示它吗?感谢您的帮助。
    • 我认为你是对的。现在知道为什么以前没有发生过。再次感谢
    • 很高兴它成功了,如果您确实看到需要自定义 ModelLoader 才能使其离线加载 GIF 的行为,请在 GitHub (github.com/bumptech/glide/issues/new) 上打开一个问题,以便我们调查它,它绝对不应该是必要的。
    • @Sam Judd 是否可以将缓存的图像从 Glide 的缓存/文件夹复制到我的设备文件夹?
    • @SamJudd 只是一个问题:如果我使用 Glide 在谷歌地图中显示标记,如果我创建一个 WeakReference 来标记使用 Glide 下载的可绘制对象有什么问题吗?因为我已经知道图像在内存中,我只想在有人触摸标记时更改标记的颜色。
    【解决方案2】:
     Glide.with(context)
     .load("http://sampleurl.com/sample.gif")
     .skipMemoryCache(true)
     .into(imageView);
    

    你已经注意到我们调用了 .skipMemoryCache(true) 来明确告诉 Glide 跳过内存缓存。这意味着 Glide 不会将图像放入内存缓存中。重要的是要理解,这只会影响内存缓存! Glide 仍然会利用磁盘缓存来避免另一个网络请求对相同图像 URL 的下一个请求。更多信息请阅读这里 Glide Cache & request optimization.

    编码愉快!!

    【讨论】:

      猜你喜欢
      • 2011-10-29
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-17
      相关资源
      最近更新 更多