使毕加索中的缓存无效


76

我使用Picasso从磁盘加载图像,例如,Picasso.with(ctx).load(new File("/path/to/image")).into(imageView)但是每当我在该文件中保存新图像并刷新时ImageView,Picasso仍然会缓存位图。

是否有可能使毕加索的缓存无效?


1
之后Picasso.with(getActivity()).invalidate(file);如何再次缓存?
tux-world,

Answers:


86

在最近的Picasso版本中,有一个新的作废方法,没有任何解决方法,因此,我认为前面提到的自定义PicassoTools类现在在这种情况下已过时

Picasso.with(getActivity()).invalidate(file);

3
好吧,这确实会使单个文件无效。仍然没有方法可以使所有缓存无效。无论如何,我将近一年前回答了这个问题,所以我不奇怪他们从那时起添加了它。
shalafi

是的,它确实使单个文件无效,正如作者希望的那样,不需要清除整个缓存,这是无效的。一年前,您是否尝试过在毕加索中自己实现它?
2015年

确保您使用的是最新版的毕加索,否则IllegalStateException可能会抛出。github.com/square/picasso/commit/...
贾里德Rummler

8
invalidate无法正常工作,映像仍保留在磁盘缓存中
user5155835

8
您需要加载与图像Picasso.with(imageView.getContext()).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);为无效()不清除缓存联网
乔·马赫

82

实际上,根据您自己的答案,有一种更简便的方法,而无需分叉库。将此类添加到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));

21
您不必访问该jar。您必须创建此文件并将其放在正确的包(com.squareup.picasso)中
shalafi 2014年

4
如果您将Gradle与Android Studio结合使用,而不是附加jar文件,是否可以执行此操作?
TheLettuceMaster 2014年

3
不,您不需要触摸Picasso jar,只需要在正确的包中创建文件即可。
shalafi 2014年

7
可惜,那Picasso.with(getApplication()).cache.clear();是行不通的。这样会更清洁。
Michael Schmidt

3
Picasso.cache字段不可见!
伊曼·马拉希

65

通过以下方式中止内存缓存和磁盘缓存检查:通过标志emoryPolicy.NO_CACHE和NetworkPolicy.NO_CACHE指示内存策略,如下代码片段所示:

   mPicasso.with(mContext)
            .load(url)
            .memoryPolicy(MemoryPolicy.NO_CACHE )
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .resize(512, 512)
            .error(R.drawable.login)
            .noFade()
            .into(imageView);

1
谢谢!添加.networkPolicy(NetworkPolicy.NO_CACHE)对我有用。
CanUludağ15年

1
通过这个答案,图像永远不会被缓存!那为什么要使用它呢?
伊曼·马拉希

9
@ImanMarashi它,如果你通常用相同的URL和不同的图像值(实例的工作是有用的:amazonws.com/yourProject/user_profile_images/user1/profile.jpg的网址永远不会改变,但它的价值呢。
博尔哈

14

尝试使用:

Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)

这行得通,但是我希望图像将图像存储到缓存中,如果我们知道图像是过时的,就不要从中读取!我发现无法在Picasso中按原样进行操作,因此我将标记为正确答案。
Maarten 2014年

我想以某种方式刷新以前加载的图像。skipMemoryCache()起到了作用!谢谢!
russellhoff 2015年

现在已弃用
Rob

12

如果要一次删除所有缓存,可以做的是创建一个custom 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
vmeyer

12

在Picasso中搜索图像的顺序为:内存缓存->磁盘缓存->网络

因此,在少数情况下,我们需要使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缓存检查磁盘

     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来管理缓存。


11

另一个选择是删除缓存目录本身,例如在应用程序启动时:

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您可以为我解决这个问题吗?stackoverflow.com/questions/33657619/…。我已经成功地使用了您的方法,但是现在遇到了问题。在此先感谢
madsongr

1
其他答案只是摆脱了“内存缓存”,而不是“光盘缓存”-这也照顾了光盘!:)
Mohit Singh

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

6

循环不漂亮,但是这种方法解决了我的缓存和毕加索问题。仅当您要使特定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);

2

这里接受的答案缺少一个非常重要的部分。我从这里找到了窍门: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);

希望这会有所帮助。


1

您可以通过以下方式跳过内存缓存 skipMemoryCache()

见以下

        Picasso.with(this)
            .load(IMAGE_URL)
            .skipMemoryCache()
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.no_image)
            .into(mImageViewPicasso);

摇动 compile "com.squareup.picasso:picasso:2.4.0"


0

另一种选择是将新图像保存到与原始图像不同的文件中。由于Picasso位图缓存是从文件路径中键入的,因此从其他文件加载新图像会导致缓存未命中。这还具有不必清除整个缓存的副作用。


0

使用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(),以便重新使用它


0
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
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.