使毕加索中的缓存无效

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

【讨论】:

以上是关于使毕加索中的缓存无效的主要内容,如果未能解决你的问题,请参考以下文章

如何清理毕加索的内存缓存?

如何更改 Okhttp 中的默认缓存策略?

使用 Retrofit、okhttp 和 picasso 缓存图像和字符串

将 Square Picasso 的缓存大小限制为最大 60MB

mysql时间字段加索引后如何生效

BaseAdapter 和毕加索问题