I am searching for a way, to cache images from the storage on google firebase platform. For now, I can download images, and show these to users, but I am not able to cache this, and access, even without internet connection. The database can be accessed offline. So I thought, there would be a way for storage too. I don't want to download every single image to storage, cause then I would need to check everytime, if the image is still up to date, it may be changed. Here are few links, what I could find, but no answer for my question. Maybe someone know a workaround, or a way how to accomplish it. Thanks!
Download files:
https://firebase.google.com/docs/storage/android/download-files
Cache (offline) database:
https://firebase.google.com/docs/database/android/offline-capabilities
UPDATE 1
Here is how I "cache" files with picasso, I added activity, that cares the download:
Picasso.with(getApplicationContext())
.load(uri.toString())
.networkPolicy(NetworkPolicy.OFFLINE)
.into(image1);
Any help is welcome. Thanks!
I'm afraid the Firebase SDK doesn't provide image caching by itself. But there are several great libraries that could do it for you. They download image, show it in an ImageView and cache it in a single line of code. Just request the Firebase for an image download url and feed it to the image caching library.
Something like this, if you choose Picasso as a caching library:
storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Got the download URL for 'users/me/profile.png'
// Pass it to Picasso to download, show in ImageView and caching
Picasso.with(context).load(uri.toString()).into(imageView);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
UPD: To use disk caching with Picasso you need to explicitly setup OkHttpDownloader. Look here How do I use disk caching in Picasso?
Thanks to #ATom for notice. Api has changed, and FirebaseUI 3.0 now uses Glide 4.x
Here is updated sample:
To load an image from a StorageReference, first register in your
AppGlideModule:
#GlideModule
public class MyAppGlideModule extends AppGlideModule {
#Override
public void registerComponents(Context context, Glide glide, Registry registry) {
// Register FirebaseImageLoader to handle StorageReference
registry.append(StorageReference.class, InputStream.class,
new FirebaseImageLoader.Factory());
}
}
Then you can load a StorageReference into an ImageView:
// Reference to an image file in Cloud Storage
StorageReference storageReference = ...;
// ImageView in your Activity
ImageView imageView = ...;
// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
.load(storageReference)
.into(imageView);
And don't forget to add dependency in your build.gradle:
implementation 'com.firebaseui:firebase-ui-:3.1.0'
Answer source on GitHub
Old answer:
FirebaseUI 1.0 now released. Storage example has class FirebaseImageLoader
Images displayed using FirebaseImageLoader are cached by their path in
Firebase Storage, so repeated loads will be fast and conserve
bandwidth.
// Reference to an image file in Firebase Storage
StorageReference storageReference = ...;
// ImageView in your Activity
ImageView imageView = ...;
// Load the image using Glide
Glide.with(this /* context */)
.using(new FirebaseImageLoader())
.load(storageReference)
.into(imageView);
I had the same issue. Tried all possible ways but couldn't fix that. I think the problem lies with the links generated by firebase storage. Picasso generally caches the images it loads. I have tried other cloud services like cloudinary, LibPixel whose links end with image format (Eg:.jpg) and picasso caches these link images. While firebase links end with token numbers. Strange thing it fails!
Related
I'm trying to get an image from my Firebase Storage in Android Studio
and set the image to ImageView. How can I get the image from Firebase storage?
What I've tried:
mStorageImage=FirebaseStorage.getInstance().getReference().child("Profile_Images").child("UserName");
mStorageImage.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Picasso.with(AccountView.this).load(uri).fit().centerCrop().into(profileImage);
}
});
You must select your image url form right side of the console inside the file location.The steps are given below
Step.1. Select Download location form your console(Its should be visible inside the file location)
Use Picasso or glide or whatever suits you to implement easily. Here I was implemented the glide library for display the images.
String url="Firebase download url";
You can also use activity Instant of myFragment
Glide
.with(myFragment)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.crossFade()
.into(myImageView);
I am using Glide in one of my projects to show image from file.
Below is my code how I am showing the image:
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath))
.into(mImage);
The image at this location(imagePath) keeps on changing. By default Glide cache the image it shows in the ImageView. Because of this, the Glide was showing the first image from cache for new images at that location.
If I change the image at location imagePath with some other image having same name then the Glide is showing the first image instead of new one.
Two queries are:
Is it possible to always the image from File and not cache? This way problem will be solved.
Is it possible to clear image from cache before getting newly replaced image? This will also solve the problem.
This is how I solved this problem.
Method 1: When the URL changes whenever image changes
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(mImage);
diskCacheStrategy() can be used to handle the disk cache and you can skip the memory cache using skipMemoryCache() method.
Method 2: When URL doesn't change, however, image changes
If your URL remains constant then you need to use Signature for image cache.
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new StringSignature(yourVersionMetadata))
.into(yourImageView);
Glide signature() offers you the capability to mix additional data with the cache key.
You can use MediaStoreSignature if you are fetching content from media store. MediaStoreSignature allows you to mix the date modified time, mime type, and orientation of a media store item into the cache key. These three attributes reliably catch edits and updates allowing you to cache media store thumbs.
You may StringSignature as well for content saved as Files to mix the file date modified time.
As explained in the section Caching and Cache Invalidation of the Glide wiki:
Because File names are hashed keys, there is no good way to simply
delete all of the cached files on disk that correspond to a particular
url or file path. The problem would be simpler if you were only ever
allowed to load or cache the original image, but since Glide also
caches thumbnails and provides various transformations, each of which
will result in a new File in the cache, tracking down and deleting
every cached version of an image is difficult.
In practice, the best way to invalidate a cache file is to change your >identifier when the content changes (url, uri, file path etc).
Since you can't change the file path, Glide offers the signature() API that allows you sets some additional data to be mixed in to the memory and disk cache keys allowing the caller more control over when cached data is invalidated.
If you want to reload every time the image from the disk, you can change your code like this:
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath))
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
.into(mImage);
There are two ways to handle Glide cache refresh,
Firstway: - Add below with glide implementation
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
Second way:
If you able to identify image changes then give your new file name in below,
.signature(new StringSignature(String.valueOf(fileName)))
or you want to load every time with latest images , use below
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
Hope this helps.
This will remove cache memory which is stored by Glide.And it should be done in background otherwise it will throw exception
new Thread(new Runnable() {
#Override
public void run() {
Glide.get(MainActivity.this).clearDiskCache();
}
}).start();
Had troubles with Glide 4.2.0, StringSignature was not resolved.
Looks like StringSignature is not available anymore and you have to use ObjectKey instead.
So code looks like
Glide.with(imageView).
load(pathToImage).
apply(new RequestOptions().signature(new ObjectKey("signature string"))).
into(imageView);
If you save images to the same known filename as a convention and want to invalidate the Glide cache only when the file has changed, using the file modification timestamp can work well.
I was using such a convention for avatar images which I was downloading to File objects outside Glide, and then using Glide just to efficiently resize and make them round, etc.
So I ended up using the StringSignature strategy with the value of the file's lastChanged timestamp as the signature. Here's what the fluent code for that looks like:
Glide.with(this)
.load(avatarFile)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.signature(new StringSignature(String.valueOf(avatarFile.lastModified())))
.into(ivProfile);
}
where avatarFile is my java.io.File object, of course.
I had troubles with setting signature using Glide version 4.* with Kotlin.
After some time I ended up with this:
fun ImageView.loadUrl(url: String) {
var requestOptions = RequestOptions()
requestOptions.signature(ObjectKey(System.currentTimeMillis()))
Glide.with(this).load(url).apply(requestOptions).into(this)
}
It's an extension function for ImageView, and it's used this way:
imageView.loadUrl(url)
I Hope it will help someone
For Glide 4.3.+ library you need to something like this to ,
Glide.with(context)
.load(image_path)
.apply(new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true))
.into(imge_view);
In the latest versions we should use RequestOptions
RequestOptions Provides type independent options to customize loads with Glide in the latest versions of Glide.
Make a RequestOptions Object and use it when we are loading the image.
RequestOptions requestOptions = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE) // because file name is always same
.skipMemoryCache(true);
Glide.with(this)
.load(photoUrl)
.apply(requestOptions)
.into(profile_image);
I was using Glide to load a File, and here's what I ended up doing to make sure Glide's disk cache was invalidated every time my file changed (even though it had the same path):
Glide.with(context)
.load(bitmapFile)
.signature(new ObjectKey(bitmapFile.lastModified()))
.into(imageView);
I worked on this for days, and all the above-mentioned solutions are just slow as a sloth.
I know you've probably read this before and ignored it because you thought it would probably take a lot of work to change your code. But seriously, it's well worth it. The performance, as far as I can tell, beats all the other methods presented, it's Glide's recommended solution, AND you don't need to skip cache or create signatures so it keeps your code cleaner too.
FROM Glide:
In practice, the best way to invalidate a cache file is to change your
identifier when the content changes (url, uri, file path etc) when
possible. - https://bumptech.github.io/glide/doc/caching.html
SOLUTION:
Change the name of the image when the user uploads a new image. Get the file name and use that for example. Once the image URL has changed, Glide understands you have changed the image and will update the Cache accordingly. This has by far given me the best performance.
WHEN USING:
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
It never caches the images and this really makes images load slowly. You'd think Signatures are better for performance, but to me they seemed just as slow.
signature with GlideApp
GlideApp.with(imageView)
.load(url)
.signature(new ObjectKey(System.currentTimeMillis()))
.placeholder(R.drawable.sky)
.error(R.drawable.sky)
.into(imageView);
And finally Kotlin implementation (For Fragments):
Glide.with(activity)
.load(url)
.apply(RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true))
.into(myImageView)
This worked for me
//use diskCacheStrategy(DiskCacheStrategy.NONE) after skipMemoryCache(true)
Glide.with(this)
.load(image)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageview);
Programmatically simply you can use:
// must run on main thread
Glide.get(getApplicationContext()).clearMemory();
// must run in background thread
Glide.get(getApplicationContext()).clearDiskCache();
For More
This one worked for me!
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(mImage);
To benefit from the cache provided by Glide and ensure that the correct image is shown everytime, you can use the signature() API.
All you have to do is to set as signature an information that relates to the image file. When you replace that file, the information changes too and Glide knows it must reload it, ignoring the cache.
A valid information could be a digest (for example SHA-1) calculated on the file contents.
Glide.with(context)
.load(inputFile)
.signature(new StringSignature(sha1(inputFile)))
.into(targetImageView);
Here I found the following implementation of sha1() function:
public static String sha1(final File file) throws NoSuchAlgorithmException, IOException {
final MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
try (InputStream is = new BufferedInputStream(new FileInputStream(file)) {
final byte[] buffer = new byte[1024];
for (int read = 0; (read = is.read(buffer)) != -1;) {
messageDigest.update(buffer, 0, read);
}
}
// Convert the byte to hex format
try (Formatter formatter = new Formatter()) {
for (final byte b : messageDigest.digest()) {
formatter.format("%02x", b);
}
return formatter.toString();
}
}
1) First clear disk cache.
private class ClearGlideCacheAsyncTask extends AsyncTask<Void, Void, Boolean>{
private boolean result;
#Override
protected Boolean doInBackground(Void... params) {
try {
Glide.get(getContext()).clearDiskCache();
result = true;
}
catch (Exception e){
}
return result;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if(result)
Toast.makeText(getActivity(), "cache deleted", Toast.LENGTH_SHORT).show();
}
}
You can call from your ui with new ClearGlideCacheAsyncTask ().execute();
2) Clear memory cache
// This method must be called on the main thread.
Glide.get(context).clearMemory();
Source : https://bumptech.github.io/glide/doc/caching.html
you can use a time stamp, that time could be the file's date modified or System.currentTimeMillis()
this works perfectly
Glide.with(DemoActivity.this)
.load(Uri.parse("file://" + imagePath+"?time="+System.currentTimeMillis()))
.into(mImage);
Scenario:
I have a large GIF image which I want to cache the first time user opens the app using Glide - Image Loading and Caching library. After that whenever user opens the app, I want to show the cached version if present. This GIF URL will expire after a given interval. When it expires, I fetch the new GIF URL and display/cache that for future use.
What I tried:
I went through Caching and Cache Invalidation on Glide's github page. I also went though the Google Group thread Ensuring That Images Loaded Only Come From Disk Cache, which shows how to get the image form cache. I also went through How to invalidate Glide cache for some specific images question.
From the links above I see the following code sniplet which shows how to load the image from cache. However this only tries to get the image from cache. If its not present in cache, it doesn't try to get from the network and fails:
Glide.with(TheActivity.this)
.using(new StreamModelLoader<String>() {
#Override
public DataFetcher<InputStream> getResourceFetcher(final String model, int i, int i1) {
return new DataFetcher<InputStream>() {
#Override
public InputStream loadData(Priority priority) throws Exception {
throw new IOException();
}
#Override
public void cleanup() {
}
#Override
public String getId() {
return model;
}
#Override
public void cancel() {
}
};
}
})
.load("http://sampleurl.com/sample.gif")
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(theImageView);
Questions:
Is there a cleaner way to achieve the following: Show the GIF image from the cache if present else download the GIF, cache it for later use and show it in the ImageView.
The caching article above mentions the following:
In practice, the best way to invalidate a cache file is to change
your identifier when the content changes (url, uri, file path etc)
The server sends a different URL to the app when the previous one expires. In this case, I believe the old image will eventually be Garbage Collected? Is there a way to force remove the image from the cache?
On a similar note, is there a way to prevent the Garbage Collection of an image with specific key (to prevent downloading the large file again) and then later instruct to delete the old image from cache when the URL changes?
You don't need a custom ModelLoader to show the GIF from cache if present and fetch it otherwise, that's actually Glide's default behavior. Just using a standard load line should work fine:
Glide.with(TheActivity.this)
.load("http://sampleurl.com/sample.gif")
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(theImageView);
Your code will prevent Glide from downloading the GIF and will only show the GIF if it is already cached, which it sounds like you don't want.
Yes, the old image will eventually be removed. By default Glide uses an LRU cache, so when the cache is full, the least recently used image will be removed. You can easily customize the size of the cache to help this along if you want. See the Configuration wiki page for how to change the cache size.
Unfortunately there isn't any way to influence the contents of the cache directly. You cannot either remove an item explicitly, or force one to be kept. In practice with an appropriate disk cache size you usually don't need to worry about doing either. If you display your image often enough, it won't be evicted. If you try to cache additional items and run out of space in the cache, older items will be evicted automatically to make space.
Glide.with(context)
.load("http://sampleurl.com/sample.gif")
.skipMemoryCache(true)
.into(imageView);
You already noticed that we called .skipMemoryCache(true) to specifically tell Glide to skip the memory cache. This means that Glide will not put the image in the memory cache. It's important to understand, that this only affects the memory cache! Glide will still utilize the disk cache to avoid another network request for the next request to the same image URL.for more read this
Glide Cache & request optimization.
Happy coding!!
So, I was starting my project and wants to use Picasso in my project because its popular and used by many projects out there.
I included picasso using gradle and tried loading facebook profile url with this. http://graph.facebook.com/rohitiskul/picture.
It worked very well. It loaded image from network without any issues. I restarted the app.(Without actually killing the process). It showed me the same image instantly cached in Memory.
But then, I killed the app (force stop) and restarted. It took almost 10+ seconds to load the image. And that image was loading from the disk when I checked in the debug logs.
My code looks like this -
In MainActivity-
Picasso.with(context)
.load("http://graph.facebook.com/rohitiskul/picture")
.into(imageView);
In application class-
Picasso picasso = new Picasso.Builder(this)
.indicatorsEnabled(true).loggingEnabled(true).build()
Picasso.setSingletonInstance(picasso);
Anyone with the similar problem? Any solution would be helpful.
I tried loading same Url with UniversalImageLoader and it was fast when fetching cached image from disk.
Edit
Earlier while playing with my app, I found out that Picasso wasn't loading the disk cached image when device was offline.
I encounter the same problem,
but find only slow for the first image, later images will be fast.
Probably it needs a warm-up (loading index cache) ?
Okay i got your problem. I have fixed it by doing this
Picasso.with(context)
.load("http://graph.facebook.com/rohitiskul/picture")
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, new Callback() {
#Override
public void onSuccess() { }
#Override
public void onError() {
// Try again online if cache failed
Picasso.with(context)
.load("http://graph.facebook.com/rohitiskul/picture")
.into(imageView);
}
});
Explanation:
Picasso will look for images in cache.
If it failed only then image will be downloaded over network. In your case from facebook.
This issue I had also faced earlier, with this what I understood that Picasso refer the cached image based on image name mentioned in the URL.
In your case you don't have image name in URL like 'image1.jpg'. Due to which Picasso is finding it difficult to read from cache and it downloads the image everytime
You can give a try to image containing the image name in URL and that will work
Picasso doesn't offer disk cache out of the box. Instead, it relies on an Http Cache.
Make sure you add OkHttp to your dependency list.
Add a string identifier with the stableKey method when making the request so Picasso can identify your requests and quickly load it from the cache.
Example:
Picasso.Builder(context).loggingEnabled(true).build()
.load(imageUrl)
.stableKey("myImage")
.into(imageView)
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?
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);
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));
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);
Try to use:
Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)
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.
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.
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();
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();
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);
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.
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"
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.
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
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));