使毕加索中的缓存无效
Posted
技术标签:
【中文标题】使毕加索中的缓存无效【英文标题】:Invalidate cache in Picasso 【发布时间】:2014-03-27 19:19:16 【问题描述】:我使用Picasso 从磁盘加载图像,例如Picasso.with(ctx).load(new File("/path/to/image")).into(imageView)
,但每当我在该文件中保存新图像并刷新我的ImageView
时,Picasso 仍然会缓存位图。
Picasso 中的缓存可以失效吗?
【问题讨论】:
Picasso.with(getActivity()).invalidate(file);
之后如何再次缓存?
【参考方案1】:
在最近的 Picasso 版本中,有一种新的无效方法,没有任何解决方法,所以我认为前面提到的自定义 PicassoTools 类在这种情况下现在已经过时了
Picasso.with(getActivity()).invalidate(file);
【讨论】:
嗯,这确实使单个文件无效。仍然没有使所有缓存失效的方法。无论如何,我差不多一年前就回复了,所以从那以后他们添加了它我并不感到惊讶。 是的,它确实使单个文件无效,正如作者想要的那样,不需要清除整个缓存,它没有效果。您是否在一年前尝试自己在 Picasso 中实现它? 确保您使用的是最新版本的毕加索,否则IllegalStateException
可能会被抛出。 github.com/square/picasso/commit/…
invalidate 无效,图像仍保留在磁盘缓存中
您需要使用Picasso.with(imageView.getContext()).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
加载图像,因为invalidate() 不会清除网络缓存【参考方案2】:
实际上,根据您自己的答案,有一种更简单的方法可以做到这一点,而无需分叉库。将此类添加到 com.squareup.picasso 包中。
package com.squareup.picasso;
public class PicassoTools
public static void clearCache (Picasso p)
p.cache.clear();
因为缓存具有包可见性,所以这个 util 类可以为您清除缓存。你只需要调用它:
PicassoTools.clearCache(Picasso.with(context));
【讨论】:
您不必访问 jar。您必须创建此文件并将其放在正确的包中 (com.squareup.picasso) 如果您在 android Studio 中使用 Gradle 而不是附加 jar 文件,有没有办法做到这一点? 不,你不需要触摸毕加索的罐子,你只需要在正确的包中创建文件。 很遗憾,Picasso.with(getApplication()).cache.clear();
不起作用。会干净很多。
Picasso.cache 字段不可见!!【参考方案3】:
Abort memory cache and disk cache check by 指示内存策略 by flag: emoryPolicy.NO_CACHE 和 NetworkPolicy.NO_CACHE 如下代码 sn-p:
mPicasso.with(mContext)
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE )
.networkPolicy(NetworkPolicy.NO_CACHE)
.resize(512, 512)
.error(R.drawable.login)
.noFade()
.into(imageView);
【讨论】:
谢谢!添加 .networkPolicy(NetworkPolicy.NO_CACHE) 对我有用。 通过这个答案,图像永远不会被缓存!那为什么要使用它呢? @ImanMarashi 如果您通常使用相同的 url 和不同的图像值(例如:amazonws.com/yourProject/user_profile_images/user1/profile.jpg。url 永远不会改变,但它的值会改变) .【参考方案4】:尝试使用:
Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)
【讨论】:
这行得通,但是我希望图像 store 图像进行缓存,如果我们知道图像是陈旧的,就不要从中读取!我发现在 Picasso 中无法按原样执行此操作,因此我会将您的答案标记为正确。 我想以某种方式刷新之前加载的图像。 skipMemoryCache() 成功了!谢谢! 现在已弃用【参考方案5】:毕加索中搜索图片的顺序为: 内存缓存 -> 磁盘缓存 -> 网络
所以我们需要在 Picasso 中使缓存失效的场景很少:
1.使内存缓存失效:
用例:当磁盘缓存或远程主机中的映像已更新时解决方案:清除缓存的Url、File、Uri(如果存在)
mPicasso.with(appContext).invalidate(File);
mPicasso.with(appContext).invalidate(Url);
mPicasso.with(appContext).invalidate(Uri);
.
2.使内存缓存和磁盘缓存失效 在线
※注意:在线表示直接更新到ImageView
用户案例:在远程主机上更新图像
解决方案:中止内存缓存和磁盘缓存上的图像,然后请求远程主机上的图像
mPicasso.with(appContext)
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE )
.networkPolicy(NetworkPolicy.NO_CACHE)
.into(imageView);
-> 中止内存缓存和磁盘缓存
.
3.使内存缓存和磁盘缓存失效 离线
※注意:离线是指更新不更新到ImageView,只是后台获取以供稍后使用
用户案例:您知道远程主机上的图像已更新,但只想更新缓存以供以后使用(不更新到图像视图)解决方案:仅获取
mPicasso.with(appContext)
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.networkPolicy(NetworkPolicy.NO_CACHE)
.fetch();
※注意:使用 fetch() 很好,但也会消耗网络资源,所以请慎重考虑,请查看下面的方案 4 以获得更好的解决方案
4.如果存在磁盘缓存,则使内存缓存和磁盘缓存失效 离线
用户案例:仅当磁盘缓存中已存在缓存时才使缓存无效解决方案:应该使用参数检查磁盘:NetworkPolicy.OFFLINE cache before fetch
mPicasso.with(appContext)
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.networkPolicy(NetworkPolicy.OFFLINE)
.fetch(new Callback()
@Override
public void onSuccess()
//Success: mean disk cache exist -> should do actual fetch
picasso.load(url).fetch();
@Override
public void onError()
//Failed: mean disk cache not exist
);
Picasso 是一个了不起的库,我希望 squareup 在未来添加更多方便的 API 来管理缓存。
【讨论】:
【参考方案6】:另一种选择是删除缓存目录本身,例如在应用启动时:
deleteDirectoryTree(context.getCacheDir());
地点:
/**
* Deletes a directory tree recursively.
*/
public static void deleteDirectoryTree(File fileOrDirectory)
if (fileOrDirectory.isDirectory())
for (File child : fileOrDirectory.listFiles())
deleteDirectoryTree(child);
fileOrDirectory.delete();
这会删除整个缓存目录,如果您想模拟应用的首次使用,这很好。如果只想删除 Picasso 缓存,在路径中添加“picasso-cache”即可。
【讨论】:
@Lawrence Kesteloot 你能帮我解决这个问题吗? ***.com/questions/33657619/… 。我已经成功地使用了你的方法,但我现在遇到了问题。提前致谢 其他答案只是摆脱了内存缓存而不是磁盘缓存-这也可以处理光盘! :)【参考方案7】:如果你想一次删除所有缓存,你可以做的是创建一个自定义的Picasso.LruCache
,然后在上面使用clear
方法。
这是一个示例:
Picasso.Builder builder = new Picasso.Builder(this);
LruCache picassoCache = new LruCache(this);
builder.memoryCache(picassoCache);
Picasso.setSingletonInstance(builder.build());
清除缓存:
picassoCache.clear();
【讨论】:
来自 Picasso lib 的相同建议:github.com/square/picasso/issues/935【参考方案8】:您可以通过设置自己的缓存并清除它来清除毕加索的图像缓存。 此代码已在 Picasso 2.5.0 上测试
private Picasso picasso;
private LruCache picassoLruCache;
picassoLruCache = new LruCache(context);
// Set cache
picasso = new Picasso.Builder(context) //
.memoryCache(picassoLruCache) //
.build();
// Clear cache
picassoLruCache.clear();
【讨论】:
【参考方案9】:循环不好,但这种方法解决了我的缓存和毕加索问题。仅当您想使特定 URL 的缓存无效时才使用此方法,这种方法很慢,可能不是正确的方法,但对我有用。
String url = "http://www.blablabla.com/Raiders.jpg";
Picasso.with(this).invalidate(url);
Picasso.with(this)
.load(url)
.networkPolicy(
NetworkUtils.isConnected(this) ?
NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
.resize(200, 200)
.centerCrop()
.placeholder(R.mipmap.ic_avatar)
.error(R.mipmap.ic_avatar)
.into(imageView);
【讨论】:
【参考方案10】:此处接受的答案缺少一个非常重要的部分。我从这里找到了诀窍:http://blogs.candoerz.com/question/124660/android-image-cache-is-not-clearing-in-picasso.aspx
当您在显示原始图像时使用调整大小、中心裁剪等自定义选项时,只需调用以下行,就不会清除照片的缓存。
Picasso.with(getContext()).invalidate(file);
解决办法:
显示图片时,使用stableKey()
方法。
Picasso.with(getContext()).load(new File(fileUri))
.skipMemoryCache()
.placeholder(R.drawable.placeholder)
.stableKey(fileUri)
.into(imageview);
然后,您可以稍后通过调用此命令清除此文件的缓存:
Picasso.with(getContext()).invalidate(fileUri);
希望这会有所帮助。
【讨论】:
【参考方案11】:你可以通过skipMemoryCache()
跳过内存缓存
见下文
Picasso.with(this)
.load(IMAGE_URL)
.skipMemoryCache()
.placeholder(R.drawable.placeholder)
.error(R.drawable.no_image)
.into(mImageViewPicasso);
gradlecompile "com.squareup.picasso:picasso:2.4.0"
【讨论】:
【参考方案12】:另一种选择是将新图像保存到与原始图像不同的文件中。由于 Picasso 位图缓存与文件路径无关,因此从不同的文件加载新图像将导致缓存未命中。这还有一个好处,就是不必清除整个缓存。
【讨论】:
【参考方案13】:请改用shutdown()
根据源代码; shutdown 将停止接受进一步的请求并清除所有缓存
/** Stops this instance from accepting further requests. */
public void shutdown()
if (this == singleton)
throw new UnsupportedOperationException("Default singleton instance cannot be shutdown.");
if (shutdown)
return;
cache.clear();
cleanupThread.shutdown();
stats.shutdown();
dispatcher.shutdown();
for (DeferredRequestCreator deferredRequestCreator : targetToDeferredRequestCreator.values())
deferredRequestCreator.cancel();
targetToDeferredRequestCreator.clear();
shutdown = true;
您也不能关闭单例实例。
所以你需要有Picasso
的实例变量。每次shutdown()
时不要忘记重新初始化 picasso 实例以便重用它
【讨论】:
【参考方案14】:File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
【讨论】:
以上是关于使毕加索中的缓存无效的主要内容,如果未能解决你的问题,请参考以下文章
使用 Retrofit、okhttp 和 picasso 缓存图像和字符串