Picasso中的缓存无效

时间:2014-02-25 13:59:15

标签: android caching image-loading picasso

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

是否可以在Picasso中使缓存无效?

13 个答案:

答案 0 :(得分:83)

在毕加索的最新版本中,有一种新的无效方法,没有任何变通方法,所以我认为前面提到的自定义PicassoTools类现在在这种情况下已经过时了

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

答案 1 :(得分:78)

实际上,根据您自己的答案,有一种更简单的方法可以在不分支库的情况下完成。将此类添加到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));

答案 2 :(得分:62)

通过标记指示内存策略来中止内存缓存和磁盘缓存检查: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);

答案 3 :(得分:14)

尝试使用:

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

答案 4 :(得分: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”。

答案 5 :(得分:11)

如果要一次删除所有缓存,可以执行的操作是创建自定义Picasso.LruCache,然后在其上使用clear方法。

以下是一个示例:

Picasso.Builder builder = new Picasso.Builder(this);
LruCache picassoCache = new LruCache(this);
builder.memoryCache(picassoCache);
Picasso.setSingletonInstance(builder.build());

清除缓存:

picassoCache.clear();

答案 6 :(得分:9)

毕加索的搜索图像顺序为: 内存缓存 - >磁盘缓存 - >网络

因此我们需要在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来检查磁盘

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

答案 7 :(得分: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();

答案 8 :(得分: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);

希望这会有所帮助。

答案 9 :(得分:1)

您可以按skipMemoryCache()

跳过内存缓存

请参阅以下

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

gradle compile "com.squareup.picasso:picasso:2.4.0"

答案 10 :(得分:0)

另一种选择是将新图像保存到与原始图像不同的文件中。由于Picasso位图缓存是从文件路径中锁定的,因此从其他文件加载新图像将导致缓存未命中。这样做的另一个好处是无需清除整个缓存。

答案 11 :(得分:0)

使用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()时都不要忘记重新初始化毕加索实例,以便重复使用它

答案 12 :(得分:0)

File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));