Invalidate cache in Picasso
AndroidCachingImage LoadingPicassoAndroid Problem Overview
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?
Android Solutions
Solution 1 - Android
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));
Solution 2 - Android
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);
Solution 3 - Android
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);
Solution 4 - Android
Try to use:
Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)
Solution 5 - Android
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.
Solution 6 - Android
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.
Solution 7 - Android
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();
Solution 8 - Android
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();
Solution 9 - Android
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);
Solution 10 - Android
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.
Solution 11 - Android
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"
Solution 12 - Android
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.
Solution 13 - Android
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
Solution 14 - Android
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));