Glide没有更新Android上相同URL的图像?

38

我有一张图片使用了相同的URL。当我多次更新这张图片时,它显示的是之前的图片。服务器上的图片和版本已经更新,但Glide没有显示新的图片。我希望每次都能获取到新的图片并将其缓存。

Glide.with(context)
        .load(Constants.COPY_LINK_BASE_URL + info.getDisplayPicture())
        .placeholder(R.drawable.ic_profile).dontAnimate()
        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
        .signature(new (SettingManager.getUserPictureVersion(context)))
        .into(ivUserProfilePhoto);

我可以通过更改互联网连接来重现此错误,在某些互联网连接下,更改图像会按预期显示,而在其他互联网连接下,更改2到3次图像后它仍然保持不变。


您的缓存图像正在显示。请制作自己的磁盘缓存机制,并在服务器上有新图像可用时清除旧图像。查看此链接可能有帮助:https://github.com/bumptech/glide/wiki/Configuration#size - Raghunandan
2
可能是一个重复的问题,与 Captcha image cannot be refresh by using Glide 有关。 - Nouman Shah
在他的问题中,他没有使用签名 API,而我已经在使用它。 - Usman Saeed
11个回答

31
//Use bellow code, it work for me.Set skip Memory Cache to true. it will load the image every time.

 Glide.with(Activity.this)
.load(theImagePath)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(myImageViewPhoto);

1
谢谢您的回复,但这并不能满足我的要求。 - Usman Saeed
1
问题是URL无法更改。 - Usman Saeed
1
问题在于每次加载照片都会消耗时间,有些情况下,如果图像太大,甚至可能导致超时。也许将一个布尔值保存在sharedPreferences中以指示何时应重新加载URI是个好主意。 - Soon Santos
2
关闭缓存是一个非常糟糕的解决方案。 - Kocus
即使Glide获取了更新的图像(据我所知),这样做也不会更新Glide的缓存。因此,启用缓存的后续调用将不会返回先前使用“DiskCacheStrategy.NONE”获取的图像。 - hannojg
显示剩余2条评论

25

Glide 4.x

Glide.with(context)
     .load(imageUrl)
     .apply(RequestOptions.skipMemoryCacheOf(true))
     .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
     .into(imageView);

Glide 3.x

Glide.with(context)
     .load(imageUrl)
     .skipMemoryCache(true)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

23

简短概括。

  1. 您可以通过添加以下代码来跳过缓存:

    GLIDE v4

    Glide.with(context)
            .load(url)
            .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
            .apply(RequestOptions.skipMemoryCacheOf(true))
            .into(imageView);
    

    GLIDE v3

    Glide.with(context)
            .load(url)
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .skipMemoryCache(true)
            .into(imageView);
    
  2. 或者:您可以通过向您的URL添加一个虚拟的随机参数来解决缓存问题:

    Glide.with(context)
            .load(url + "?rand=" + (new Random().nextInt()))
            .into(imageView);
    

发生了什么?

当您的图片第一次加载时,它会被存储在本地缓存中。当您第二次请求时,Glide 会从缓存中获取它,就像它是一个成功的请求一样。这是为了许多好的原因,例如:卸载您的服务器、节省用户的数据和快速响应(提供给用户流畅的体验)。

该怎么办?

您需要禁用缓存,以便每次请求时强制 Glide 远程获取您的图像。您可以执行以下操作:

Glide.with(context)
         .load(url)
         .diskCacheStrategy(DiskCacheStrategy.NONE)
         .skipMemoryCache(true)
         .signature(imageVersion) // supposing that each new image has its own version number
         .into(imageView);

或者,在无法知道图片何时更改(没有imageVersion)的情况下,为每个图片使用唯一的签名。

Glide.with(context)
         .load(url)
         .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
         .into(imageView);

另一种干净的方法是在服务器上配置图片的缓存策略,并使用.diskCacheStrategy(DiskCacheStrategy.SOURCE)

值得一提的巧妙技巧

如果向目标URL添加一个虚拟的GET参数不会造成任何问题,那么你可以通过每次获取图片时传递一个随机参数来绕过缓存。这将强制Glide从服务器拉取您的图片,因为缓存中不可能存在具有该随机URL的图片。

Glide.with(context)
         .load(url + "?rand=" + (new Random().nextInt())) // "&rand=" if your url already has some GET params
         .into(imageView);

Glide缓存API 在这里


由于需求,我不能每次加载图片。 - Usman Saeed
如果您想保留缓存,可以在服务器中添加一些额外的代码来查看图像是否已更改。如果它已更改,则会清除缓存并加载更新的图像,否则只需从缓存中获取即可。 - Anis LOUNIS aka AnixPasBesoin
签名来自服务器,告诉我们URL上的图像已经被更改。 - Usman Saeed
1
这个解决方案对我很有效。唯一需要改变的是使用不同的对象来代替建议中的签名“ObjectKey(System.currentTimeMillis().toString())”。如果你正在使用Glide 4及以上版本,这会有所帮助。 - mask

9
在我的情况下,Glide无法识别.signature(),因此除了@MGDavies的答案之外,您可能还需要像这样的东西。
// in kotlin
Glide.with(context)
        .load("url")
        //using apply to RequestOptions instead signature directly
        .apply(RequestOptions().signature(ObjectKey("time that image was updated")))
        .into(thumb)

6
这是一个旧问题,我相信你现在已经解决了它。不过,我认为Picasso和Glide这两个大型库现在都支持类似的功能。 Glide有其特色API供您查看: https://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
Glide.with(yourFragment)
    .load(yourFileDataModel)
    .signature(new StringSignature(yourVersionMetadata))
    .into(yourImageView);

我自己还没有机会使用过这个,但看起来你需要调用API获取版本元数据,然后进行后续的调用以完成它。
或者,可以考虑使用ETags。
祝好运!

4
Glide 4.8.0
Glide.with(mContext).asBitmap()
                    .load(nopicUrl)
                    .apply(RequestOptions.skipMemoryCacheOf(true))
                    .apply(RequestOptions.signatureOf(new ObjectKey(String.valueOf(System.currentTimeMillis()))))
                    .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA))
                    .into(ivImageView);

3

现在使用最新的Glide版本,您需要使用RequestOption来清除缓存。

RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true);

如果您想每次加载图片都使用一个 字符串 作为 signature,则可以这样做。

RequestOptions options = new RequestOptions()
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())));

最后:
Glide.with(CompressSingleActivity.this)
.applyDefaultRequestOptions(options)
.load(currentFile)
.into(currentImageView);

2
当新图片被加载或更新时,请使用以下内容清除 Glide 内存和缓存:

|==| 清除 Glide 内存

 Glide.get(getApplicationContext()).clearMemory();
|==| 清除 Glide 缓存()
void clearGlideDiskCache()
{
    new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            Glide.get(getApplicationContext()).clearDiskCache();
        }
    }).start();
}

4
仅为了清除单个图像的缓存,这似乎非常浪费。很好知道,但不建议将其作为特定问题的解决方案。 - Gibolt

1

diskCacheStrategyskipMemoryCache在我的情况下不起作用。

我在Glide请求相同url的图片之间写入本地图像文件。我的解决方法是在文件名末尾添加0/1来切换文件。

强制每次更改图像源似乎可以解决问题。


0

尝试使用RequestOptions:

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.ic_placeholder);
requestOptions.error(R.drawable.ic_error);

Glide.with(context)
     .setDefaultRequestOptions(requestOptions)
     .load(url).into(holder.imageView);

如果 .setDefaultRequestOptions(requestOptions) 不起作用,可以使用 .apply(requestOptions):
Glide.with(MainActivity.this)
            .load(url)
            .apply(requestOptions)
            .into(imageview);
 // or this
 Glide.with(MainActivity.this)
            .load(url)
            .apply(new RequestOptions().placeholder(R.drawable.booked_circle).error(R.drawable.booked_circle))
            .into(imageview);

 // or this
 Glide.with(MainActivity.this)
            .load(url)
            .apply(RequestOptions.placeholderOf(R.drawable.booked_circle).error(R.drawable.))
            .into(imageview);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接