从Glide库的缓存中删除图像


75

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

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

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

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

如果我在imagePath其他位置使用相同名称的其他图像来更改图像,则Glide将显示第一个图像而不是新的图像。

两个查询是:

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

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

Answers:


148

这就是我解决这个问题的方法。

方法1:每当图像更改时URL更改

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

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

方法2:但是,当URL不变时,图像也会改变

如果您的URL保持不变,则需要使用签名进行图像缓存。

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

Glide signature()为您提供了将其他数据与缓存键混合的功能。

  • MediaStoreSignature如果要从媒体存储中获取内容,则可以使用。MediaStoreSignature允许您将日期修改时间,哑剧类型和媒体存储项目的方向混合到缓存键中。这三个属性可靠地捕获了编辑和更新,使您可以缓存媒体存储库。
  • 您也可以StringSignature将另存为“文件”的内容与文件日期修改时间混在一起。

这个对我有用。确保您实际上正在更改图片。
JuanJoséMeleroGómez17年

15
请注意,随着Glide v4StringSignature已被替换ObjectKey,请参阅Glide v4缓存
Curly

在这种方法中,如果我们使用不同版本的相同网址,那么在传递版本时是否会加载相关版本?
Ishan Fernando

3
您没有解决第二个问题“是否有可能在获取新替换的图像之前从缓存中清除图像?这也将解决此问题。”
尼克

1
虽然有效,但每次使用这种方法加载图像的速度都非常缓慢
Fluffy T Rex

55

如Glide Wiki的缓存和缓存无效部分中所述:

由于文件名是哈希键,因此没有简单的方法可以简单地删除磁盘上所有与特定URL或文件路径相对应的缓存文件。如果只允许您加载或缓存原始图像,则问题会更简单,但是由于Glide还会缓存缩略图并提供各种转换,因此每次转换都会在缓存中产生一个新的File,从而跟踪并删除每个缓存的版本图像很难。

实际上,使高速缓存文件无效的最佳方法是在内容更改(URL,uri,文件路径等)时更改> identifier。

由于您无法更改文件路径,因此Glide提供了signature() API,该API使您可以将一些其他数据混合到内存和磁盘缓存键中,从而使调用者可以更好地控制缓存数据何时无效。

如果您希望每次从磁盘重新加载映像,都可以像这样更改代码:

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

这非常适合我的需求。我有用于数据的版本,因此只要.signature(new StringSignature(Integer.toString(data.getVersion())))更改版本,只需添加即可强制更新图像。
Krøllebølle

@Mattia Maestrini谢谢,您的解决方案将单个图像更新到缓存中System.currentTimeMillis()
DolDurma '16

1
因此,我猜测这不会污染缓存目录,因为该URL被隐含为常数吗?那意味着它将覆盖以前的缓存条目?
TheRealChx101 '19

供Kotlin使用 .signature(ObjectKey(System.currentTimeMillis())))
Yonko Kilasi

35

有两种方法可以处理Glide缓存刷新,

第一步: -在以下添加滑行实现

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

第二种方式:

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

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

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

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

希望这可以帮助。


32

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

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

1
那么在删除缓存后,系统如何决定停止正在运行的线程?
Yash Agrawal

1
@YashAgrawal:它将由内部结构决定。因此,无需担心
Anand Savjani

23

使用Glide 4.2.0遇到了麻烦,StringSignature但无法解决。

似乎StringSignature不再可用,您必须使用ObjectKey

所以代码看起来像

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

16

如果将图像保存为与约定相同的已知文件名,并且只想在文件更改后才使Glide缓存无效,则使用文件修改时间戳可以很好地工作。

我将这样的惯例用于化身图像File,然后将其下载到Glide外部的对象,然后使用Glide只是为了有效地调整大小并使它们变圆,等等。

因此,我最终使用了该StringSignature策略,并以文件的lastChanged时间戳记的值作为签名。这是流利的代码如下所示:

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

avatarFile我的java.io.File目标在哪里?


14

我在Kotlin上使用Glide 4. *版设置签名时遇到了麻烦。一段时间后,我得出以下结论:

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)

我希望它可以帮助某人


1
正是我所需要的。
安东·德雷夫扬科

12

对于Glide 4.3。+库,您需要执行以下操作,

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

12

在最新版本中,我们应该使用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);


4

这对我有用

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

4

最后是Kotlin的实现(对于片段):

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

3

我花了好几天时间,上面提到的所有解决方案都像懒惰一样慢。

我知道您以前可能已经读过而忽略了它,因为您认为更改代码可能需要大量工作。但是说真的,这是值得的。据我所知,它的性能超过了所有其他介绍的方法,这是Glide推荐的解决方案,并且您无需跳过缓存或创建签名,因此也可以使代码更整洁。

FROM Glide:

实际上,使高速缓存文件无效的最佳方法是在可能的情况下更改内容(URL,URI,文件路径等)时更改标识符。- https://bumptech.github.io/glide/doc/caching.html

解决方案: 当用户上传新图像时,更改图像名称。获取文件名并使用它作为示例。图像URL更改后,Glide将了解您已更改图像,并将相应地更新缓存。到目前为止,这给了我最好的表现。

使用时:

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

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


1

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

您要做的就是将与图像文件有关的信息设置为签名。当您替换该文件时,信息也会更改,并且Glide知道它必须重新加载它,而忽略了缓存。

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

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

在这里,我找到了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();
   }
}

似乎一起使用签名,磁盘缓存和skipmemory。
Panache

1

这个为我工作!

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

1

我正在使用Glide加载File,这是我的工作,以确保每次更改文件时Glide的磁盘缓存都无效(即使它具有相同的路径):

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

1
Programmatically simply you can use,

 Glide.get(getApplicationContext()).clearMemory();
 Glide.get(getApplicationContext()).clearDiskCache();

更多


0

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();
        }
    }

您可以通过以下方式从ui致电 new ClearGlideCacheAsyncTask ().execute();

2)清除内存缓存

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.