从 Glide 库中的缓存中删除图像

Remove image from cache in Glide library

我在我的一个项目中使用 Glide 来显示文件中的图像。

下面是我如何显示图像的代码:

Glide.with(DemoActivity.this)
     .load(Uri.parse("file://" + imagePath))
     .into(mImage);

这个位置(imagePath)的图像一直在变化。默认情况下,Glide 缓存它在 ImageView 中显示的图像。正因为如此,Glide 正在为该位置的新图像显示缓存中的第一张图像。

如果我将位置 imagePath 处的图像更改为具有相同名称的其他图像,那么 Glide 将显示第一张图像而不是新图像。

两个查询是:

  1. 是否可以始终从文件中获取图像而不缓存?这样问题就迎刃而解了

  2. 是否可以在获取新替换图像之前从缓存中清除图像?这样也能解决问题。

如 Glide wiki 的 Caching and Cache Invalidation 部分所述:

Because File names are hashed keys, there is no good way to simply delete all of the cached files on disk that correspond to a particular url or file path. The problem would be simpler if you were only ever allowed to load or cache the original image, but since Glide also caches thumbnails and provides various transformations, each of which will result in a new File in the cache, tracking down and deleting every cached version of an image is difficult.

In practice, the best way to invalidate a cache file is to change your >identifier when the content changes (url, uri, file path etc).

由于您无法更改文件路径,Glide 提供了 signature() API 允许您设置一些额外的数据以混合到内存和磁盘缓存键中,从而允许调用者更多控制缓存数据何时失效。

如果你想每次都从磁盘重新加载图像,你可以像这样更改你的代码:

Glide.with(DemoActivity.this)
     .load(Uri.parse("file://" + imagePath))
     .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
     .into(mImage);

我就是这样解决这个问题的。

方法一:当URL随图片变化而变化时

Glide.with(DemoActivity.this)
    .load(Uri.parse("file://" + imagePath))
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .skipMemoryCache(true)
    .into(mImage);

diskCacheStrategy() 可用于处理磁盘缓存,您可以使用 skipMemoryCache() 方法跳过内存缓存。

方法二:当URL不变化时,图像发生变化

如果您的 URL 保持不变,那么您需要使用 Signature 进行图像缓存。

Glide.with(yourFragment)
     .load(yourFileDataModel)
     .signature(new StringSignature(yourVersionMetadata))
     .into(yourImageView);

Glide signature() 使您能够将附加数据与缓存键混合。

  • 如果您要从媒体商店获取内容,则可以使用 MediaStoreSignatureMediaStoreSignature 允许您将媒体存储项目的修改日期时间、MIME 类型和方向混合到缓存键中。这三个属性可靠地捕获编辑和更新,允许您缓存媒体存储缩略图。
  • 您也可以StringSignature将保存为文件的内容混合文件日期修改时间。

要利用 Glide 提供的缓存并确保每次显示正确的图像,您可以使用 signature() API

您所要做的就是将与图像文件相关的信息设置为签名。当你替换那个文件时,信息也会改变,Glide 知道它必须重新加载它,忽略缓存。

有效信息可以是根据文件内容计算的摘要(例如 SHA-1)。

Glide.with(context)
   .load(inputFile)
   .signature(new StringSignature(sha1(inputFile)))
   .into(targetImageView);

Here 我发现了以下 sha1() 函数的实现:

public static String sha1(final File file) throws NoSuchAlgorithmException, IOException {
   final MessageDigest messageDigest = MessageDigest.getInstance("SHA1");

   try (InputStream is = new BufferedInputStream(new FileInputStream(file)) {
     final byte[] buffer = new byte[1024];
     for (int read = 0; (read = is.read(buffer)) != -1;) {
       messageDigest.update(buffer, 0, read);
     }
   }

   // Convert the byte to hex format
   try (Formatter formatter = new Formatter()) {
     for (final byte b : messageDigest.digest()) {
       formatter.format("%02x", b);
     }
     return formatter.toString();
   }
}

这将删除由 Glide.And 存储的缓存内存,它应该在后台完成,否则会抛出异常

new Thread(new Runnable() {
          @Override
          public void run() {
             Glide.get(MainActivity.this).clearDiskCache();
          }
     }).start();

如果您按照惯例将图像保存到相同的已知文件名,并且希望仅在文件更改时使 Glide 缓存失效,那么使用文件修改时间戳可以很好地工作。

我在下载到 Glide 外部的 File 对象的头像图像上使用了这样的约定,然后使用 Glide 只是为了有效地调整大小并使它们变圆等。

所以我最终使用 StringSignature 策略,并将文件的 lastChanged 时间戳的值作为签名。流畅的代码如下所示:

Glide.with(this)
        .load(avatarFile)
        .diskCacheStrategy(DiskCacheStrategy.RESULT)
        .signature(new StringSignature(String.valueOf(avatarFile.lastModified())))
        .into(ivProfile);
}

当然,avatarFile 是我的 java.io.File 对象。

有两种方式处理Glide缓存刷新,

Firstway: - 在下面添加滑行实现

.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)

第二种方式:

如果您能够识别图像更改,请在下面给出您的新文件名,

.signature(new StringSignature(String.valueOf(fileName)))

或者您想每次都加载最新图片,请使用下面的

.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))

希望这对您有所帮助。

这对我有用

  //use  diskCacheStrategy(DiskCacheStrategy.NONE) after skipMemoryCache(true) 
         Glide.with(this)
            .load(image)
            .skipMemoryCache(true) 
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .into(imageview);

我在使用 Glide 版本 4.* 和 Kotlin 设置签名时遇到了麻烦。 一段时间后,我得到了这个:

fun ImageView.loadUrl(url: String) {
    var requestOptions = RequestOptions()
    requestOptions.signature(ObjectKey(System.currentTimeMillis()))
    Glide.with(this).load(url).apply(requestOptions).into(this)
}

是ImageView的扩展函数,使用方法是这样的:

 imageView.loadUrl(url)

希望对大家有所帮助

Glide 4.2.0 遇到问题,StringSignature 没有解决。

看起来 StringSignature 不再可用,您必须改用 ObjectKey

所以代码看起来像

Glide.with(imageView).
load(pathToImage).
apply(new RequestOptions().signature(new ObjectKey("signature string"))).
into(imageView);

使用 GlideApp 签名

    GlideApp.with(imageView)
            .load(url)
            .signature(new ObjectKey(System.currentTimeMillis()))
            .placeholder(R.drawable.sky)
            .error(R.drawable.sky)
            .into(imageView);

对于 Glide 4.3.+ 库你需要这样的东西,

Glide.with(context)
    .load(image_path)
    .apply(new RequestOptions()
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .skipMemoryCache(true))
    .into(imge_view);

在最新版本中我们应该使用 RequestOptions

RequestOptions 在最新版本的 Glide 中提供与类型无关的选项以使用 Glide 自定义加载。

创建一个 RequestOptions 对象并在我们加载图像时使用它。

 RequestOptions requestOptions = new RequestOptions()
                        .diskCacheStrategy(DiskCacheStrategy.NONE) // because file name is always same
                        .skipMemoryCache(true);

 Glide.with(this)
           .load(photoUrl)
           .apply(requestOptions)
           .into(profile_image);

最后是 Kotlin 实现(对于 Fragments):

Glide.with(activity)
            .load(url)
            .apply(RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true))
            .into(myImageView)

这个对我有用!

Glide.with(DemoActivity.this)
    .load(Uri.parse("file://" + imagePath))
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .skipMemoryCache(true)
    .into(mImage);

我正在使用 Glide 加载一个 File,下面是我最终做的事情,以确保每次我的文件更改时 Glide 的磁盘缓存都失效(即使它具有相同的路径):

Glide.with(context)
    .load(bitmapFile)
    .signature(new ObjectKey(bitmapFile.lastModified()))
    .into(imageView);

您可以简单地以编程方式使用:

 // must run on main thread
 Glide.get(getApplicationContext()).clearMemory(); 

 // must run in background thread
 Glide.get(getApplicationContext()).clearDiskCache(); 

For More

1) 首先清除磁盘缓存。

private class ClearGlideCacheAsyncTask extends AsyncTask<Void, Void, Boolean>{

        private boolean result;

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                Glide.get(getContext()).clearDiskCache();
                result = true;
            }
            catch (Exception e){
            }
            return result;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if(result)
                Toast.makeText(getActivity(), "cache deleted", Toast.LENGTH_SHORT).show();
        }
    }

您可以使用 new ClearGlideCacheAsyncTask ().execute();

从您的 ui 拨打电话

2) 清除内存缓存

// This method must be called on the main thread.
Glide.get(context).clearMemory();

来源:https://bumptech.github.io/glide/doc/caching.html

我为此工作了好几天,上面提到的所有解决方案都像树懒一样缓慢。

我知道您可能以前读过这篇文章并忽略了它,因为您认为更改代码可能需要大量工作。但说真的,这是非常值得的。据我所知,其性能胜过所有其他提出的方法,这是 Glide 推荐的解决方案,并且您不需要跳过缓存或创建签名,因此它也可以使您的代码更简洁。

来自滑翔:

In practice, the best way to invalidate a cache file is to change your identifier when the content changes (url, uri, file path etc) when possible. - https://bumptech.github.io/glide/doc/caching.html

解决方案: 当用户上传新图像时更改图像的名称。获取文件名并使用它作为示例。一旦图像 URL 发生变化,Glide 就会知道您已经更改了图像并会相应地更新缓存。 这是迄今为止我的最佳表现。

使用时:

.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)

它从不缓存图像,这确实使图像加载缓慢。您可能认为签名在性能方面更好,但对我来说它们似乎同样缓慢。