Invalidate cache in Picasso
Asked Answered
D

14

77

I load an image from disk using Picasso, e.g., Picasso.with(ctx).load(new File("/path/to/image")).into(imageView), but whenever I save a new image in that file, and refresh my ImageView, Picasso still has the bitmap cached.

Is it possible to invalidate the cache in Picasso?

Derange answered 25/2, 2014 at 13:59 Comment(1)
after Picasso.with(getActivity()).invalidate(file); how can i cache again?Cursed
B
86

In the recent versions of Picasso, there is a new method for invalidate, without any workarounds, so I think that custom PicassoTools class mentioned earlier, is now obsolete in this case

Picasso.with(getActivity()).invalidate(file);
Bristow answered 15/2, 2015 at 9:9 Comment(10)
Well, that does invalidate a single file. There is still no method to invalidate all the cache. Anyway, I replied to that almost a year ago, so I'm not surprised they have added it since then.Absently
Yes, it doe's invalidate a single file, as author wanted, there's no need to clear entire cache, it's not effective. Did you try to implement it in Picasso yourself a year ago?Bristow
Make sure you are on the latest version of Picasso or an IllegalStateException might be thrown. github.com/square/picasso/commit/…Bed
invalidate is not working, the image still remains in disk cacheOvervalue
You need to load the image with Picasso.with(imageView.getContext()).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView); as invalidate() does not clear the networking cacheCurkell
@Absently Picasso.with(getActivity()).cache.clear(); will clear all cache.Olmsted
@Bristow .invalidate(url) can be cache after get again image from url?Cursed
@Absently the field "cache" is not public anymoreMechanistic
@RJFares the field cache has always had package visibility, hence the need to put the Tools class in the correct package.Absently
@Absently i saw your answer now actually, the custom class. Can it be used to delete a specific file instead of the whole cache?Mechanistic
A
87

Actually, based on your own answer, there is an easier way to do it without forking the library. Add this class to the com.squareup.picasso package.

package com.squareup.picasso;

public class PicassoTools {

    public static void clearCache (Picasso p) {
        p.cache.clear();
    }
}

Because cache has package visibility, this util class can clear the cache for you. You just have to call it:

PicassoTools.clearCache(Picasso.with(context));
Absently answered 8/5, 2014 at 14:25 Comment(9)
How do you access this class from the jar file?Herculie
You don't have to access the jar. you have to create this file and place it in the right package (com.squareup.picasso)Absently
Is there a way to do this if you are using Gradle with Android Studio instead of the add-on jar file?Herculie
we need to create this file inside picasso jar ?Tomblin
No you don't need to touch the Picasso jar, you just need to create the file in the right package.Absently
It is a pity, that Picasso.with(getApplication()).cache.clear();does not work. It would be much cleaner.Larina
The field Picasso.cache is not visible!!Draftsman
That is why you have to put that class into the specified packageAbsently
seems doesn't work, I tried to call this function and then opened my fragment with images and it showed images in imageviews instantly (from cache)... for the first time to load them it usually takes some time, but it's still instantly and memory using by app doesn't decrease after calling this function, so DOES NOT workGrogram
B
86

In the recent versions of Picasso, there is a new method for invalidate, without any workarounds, so I think that custom PicassoTools class mentioned earlier, is now obsolete in this case

Picasso.with(getActivity()).invalidate(file);
Bristow answered 15/2, 2015 at 9:9 Comment(10)
Well, that does invalidate a single file. There is still no method to invalidate all the cache. Anyway, I replied to that almost a year ago, so I'm not surprised they have added it since then.Absently
Yes, it doe's invalidate a single file, as author wanted, there's no need to clear entire cache, it's not effective. Did you try to implement it in Picasso yourself a year ago?Bristow
Make sure you are on the latest version of Picasso or an IllegalStateException might be thrown. github.com/square/picasso/commit/…Bed
invalidate is not working, the image still remains in disk cacheOvervalue
You need to load the image with Picasso.with(imageView.getContext()).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView); as invalidate() does not clear the networking cacheCurkell
@Absently Picasso.with(getActivity()).cache.clear(); will clear all cache.Olmsted
@Bristow .invalidate(url) can be cache after get again image from url?Cursed
@Absently the field "cache" is not public anymoreMechanistic
@RJFares the field cache has always had package visibility, hence the need to put the Tools class in the correct package.Absently
@Absently i saw your answer now actually, the custom class. Can it be used to delete a specific file instead of the whole cache?Mechanistic
B
66

Abort memory cache and disk cache check by indicate memory policy by flag: emoryPolicy.NO_CACHE and NetworkPolicy.NO_CACHE as below code snippet:

   mPicasso.with(mContext)
            .load(url)
            .memoryPolicy(MemoryPolicy.NO_CACHE )
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .resize(512, 512)
            .error(R.drawable.login)
            .noFade()
            .into(imageView);
Berzelius answered 10/3, 2015 at 12:52 Comment(3)
Thanks! Adding .networkPolicy(NetworkPolicy.NO_CACHE) worked for me.Gezira
By this answer images never cached! so why use it?Draftsman
@ImanMarashi it's useful if you are usually working with same url and different image value (Example: amazonws.com/yourProject/user_profile_images/user1/profile.jpg. The url never changes, but its value does.Almshouse
I
15

Try to use:

Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)
Illumine answered 27/2, 2014 at 18:3 Comment(3)
This works, however I would like the image to store the image to cache, just not read from it if we know the image is stale! I've found out it's not possible to do that in Picasso as-is, so I'll mark your answer as correct.Derange
I wanted to refresh somehow a image which was previously loaded. skipMemoryCache() did the trick! Thanks!Zendejas
This is deprecated nowPenetralia
F
14

The order of search image in Picasso is: Memory cache -> Disk cache -> Network

So there are few scenario we need to invalidate cache in Picasso:

1.Invalidate memory cache:

  • Usercase: When image already update in disk cache or remote host
  • Solution: Clear cache of Url, File, Uri if exist

    mPicasso.with(appContext).invalidate(File);
    mPicasso.with(appContext).invalidate(Url);
    mPicasso.with(appContext).invalidate(Uri);
    

.

2.Invalidate memory cache and disk cache Online

※note: Online mean update directly to ImageView

  • User case: Image updated on remote host

  • Solution: Abort image on memory cache and disk cache then request image on remote host

    mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE )
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .into(imageView);
    

    -> Abort memory cache and disk cache

.

3.Invalidate memory cache and disk cache Offline

※ note: Offline mean update not update to ImageView, just background fetch to using later

  • User case: You know image on remote host updated, but only want to update cache only to using afterward (not update into image view)
  • Solution: fetch only

     mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE)
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .fetch();
    

※Note: Using fetch() is good but it also consume network resource, so please consider carefully, check scenario 4 in below for better solution

4.Invalidate memory cache and disk cache Offline if disk cache is exist

  • User case: Only invalidate cache if already exist in disk cache
  • Solution: Should check disk by using parameter: 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 is an amazing libs, I hope squareup will add more convenience API to manage cache in upcoming future.

Faubert answered 12/10, 2016 at 8:51 Comment(0)
L
12

Another option is to delete the cache directory itself, for example on app startup:

deleteDirectoryTree(context.getCacheDir());

where:

/**
 * Deletes a directory tree recursively.
 */
public static void deleteDirectoryTree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File child : fileOrDirectory.listFiles()) {
            deleteDirectoryTree(child);
        }
    }

    fileOrDirectory.delete();
}

That deletes the whole cache directory, which is fine if you want to simulate first-use of your app. If you only want to delete the Picasso cache, add "picasso-cache" to the path.

Leonoreleonsis answered 31/7, 2014 at 18:50 Comment(2)
@Lawrence Kesteloot could you help me with this question? #33658119 . I have already used your method with great success but I´m having problems now. Thanks in advanceWillenewillet
Other answers just get rid of Memory Cache but not Disc Cache - this takes care of the disc too! :)Vansickle
W
12

What you can do if you want to delete all cache at once, is to create a custom Picasso.LruCache, and then use the clear method on it.

Here is a sample:

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

To clear the cache:

picassoCache.clear();
Woodworking answered 20/3, 2015 at 18:42 Comment(1)
Same recommandation from Picasso lib : github.com/square/picasso/issues/935Radiocarbon
E
9

You can clear image cache of picasso by setting your own cache and clear that. This code was tested on 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();
Exhilarant answered 14/12, 2015 at 8:36 Comment(0)
P
6

Doesn't loop pretty, but this approach fixed my issue with cache and Picasso. Only use this when you want to invalidate the cache for a specific URL, this approach is slow and probably is not the correct way of doing but works for me.

    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);
Phylloquinone answered 23/4, 2015 at 2:46 Comment(0)
W
2

A very important part is missing from the accepted answer here. I found the trick from here: http://blogs.candoerz.com/question/124660/android-image-cache-is-not-clearing-in-picasso.aspx

Just calling the following line, wouldn't clear the cache of a photo when you use custom options like resize, center crop etc when displaying the original image.

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

The solution:

When displaying the image, use stableKey() method.

Picasso.with(getContext()).load(new File(fileUri))
                         .skipMemoryCache()
                         .placeholder(R.drawable.placeholder)
                         .stableKey(fileUri)
                         .into(imageview);

Then, you can clear the cache of this file later by calling this:

Picasso.with(getContext()).invalidate(fileUri);

Hope this will help.

Wink answered 28/9, 2016 at 19:34 Comment(0)
R
1

You can skip memory cache by skipMemoryCache()

see the following

        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"

Richter answered 22/3, 2017 at 5:48 Comment(0)
H
0

Another option is to save the new image into a different file than the original. Since the Picasso bitmap cache is keyed off of the file path, loading the new image from a different file will result in a cache miss. This also has the side benefit of not having to clear the entire cache.

Heaver answered 14/2, 2015 at 17:50 Comment(0)
C
0

use shutdown() instead As per source code; shutdown will stop accepting further request as well as clear all cache

 /** 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;
  }

Also you can not shutdown singleton instance. So you need to have instance variable for Picasso. Do not forget to reinitialize picasso instance everytime you shutdown() it in order to reuse it

Chad answered 15/12, 2015 at 13:59 Comment(0)
G
0
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
Geter answered 6/7, 2016 at 9:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.