从 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 将显示第一张图像而不是新图像。
两个查询是:
是否可以始终从文件中获取图像而不缓存?这样问题就迎刃而解了
是否可以在获取新替换图像之前从缓存中清除图像?这样也能解决问题。
如 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() 使您能够将附加数据与缓存键混合。
- 如果您要从媒体商店获取内容,则可以使用
MediaStoreSignature
。 MediaStoreSignature
允许您将媒体存储项目的修改日期时间、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();
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();
我为此工作了好几天,上面提到的所有解决方案都像树懒一样缓慢。
我知道您可能以前读过这篇文章并忽略了它,因为您认为更改代码可能需要大量工作。但说真的,这是非常值得的。据我所知,其性能胜过所有其他提出的方法,这是 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)
它从不缓存图像,这确实使图像加载缓慢。您可能认为签名在性能方面更好,但对我来说它们似乎同样缓慢。
我在我的一个项目中使用 Glide 来显示文件中的图像。
下面是我如何显示图像的代码:
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath))
.into(mImage);
这个位置(imagePath
)的图像一直在变化。默认情况下,Glide 缓存它在 ImageView
中显示的图像。正因为如此,Glide 正在为该位置的新图像显示缓存中的第一张图像。
如果我将位置 imagePath
处的图像更改为具有相同名称的其他图像,那么 Glide 将显示第一张图像而不是新图像。
两个查询是:
是否可以始终从文件中获取图像而不缓存?这样问题就迎刃而解了
是否可以在获取新替换图像之前从缓存中清除图像?这样也能解决问题。
如 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() 使您能够将附加数据与缓存键混合。
- 如果您要从媒体商店获取内容,则可以使用
MediaStoreSignature
。MediaStoreSignature
允许您将媒体存储项目的修改日期时间、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();
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();
2) 清除内存缓存
// This method must be called on the main thread.
Glide.get(context).clearMemory();
我为此工作了好几天,上面提到的所有解决方案都像树懒一样缓慢。
我知道您可能以前读过这篇文章并忽略了它,因为您认为更改代码可能需要大量工作。但说真的,这是非常值得的。据我所知,其性能胜过所有其他提出的方法,这是 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)
它从不缓存图像,这确实使图像加载缓慢。您可能认为签名在性能方面更好,但对我来说它们似乎同样缓慢。