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!!
I want to use picasso to load an image from a url into a placeholder, but not store that image in cache - in other words, I want the image to be downloaded from the net directly to disk and then loaded from disk when needed. I understand there's a class called RequestCreator where you can specify memory policy - does anyone have an example of using picasso/requestcreator to do something like this?
So.. something like:
RequestCreator requestCreator = new RequestCreator();
requestCreator.memoryPolicy(MemoryPolicy.NO_CACHE);
....
merged with:
Picasso.with(context).load(someurl).fit().placeholder(someplaceholder).into(sometarget)..
Picasso supports this by it's skipMemoryCache() in the Picasso builder. An example is shown below.
Picasso.with(context).load(imageUrl)
.error(R.drawable.error)
.placeholder(R.drawable.placeholder)
.skipMemoryCache()
.into(imageView);
With the new API you should use it like this so that it skips looking for it and storing it in the cache:
Picasso.with(context).load(imageUrl)
.error(R.drawable.error)
.placeholder(R.drawable.placeholder)
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.into(imageView);
NO_CACHE
Skips memory cache lookup when processing a request.
NO_STORE
Skips storing the final result into memory cache. Useful for one-off requests to avoid evicting other bitmaps from the cache.
For picasso:2.71828 or above version use the following for skipping using disk cache networkPolicy(NetworkPolicy.NO_CACHE) :
Picasso.get()
.load(camera_url)
.placeholder(R.drawable.loader2)
.networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
.into(img_cam_view);
Picasso 2.5.0
If you are using Picasso to load image from Internet, you have to use NetworkPolicy attribute.
.networkPolicy(NetworkPolicy.NO_STORE)
but live memory cache (Not disk cache) is useful, you might want to keep it.
just append this at the end of url.
"?=" + System.currentTimeMillis();
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)
Does anybody know if it is possible to clear the cached image from a single NetworkImageView using Googles Volley library?
I have an avatar image in a NetworkImageView and would like to show the new image once I have uploaded it to the server. At the moment if I do
profileImg.setImageUrl("myUrl", mImageLoader); I get the cached image.
Check this out :
1) Turning off cache :
If you want disable the cache for a particular url, you can use setShouldCache() method as below.
StringRequest stringReq = new StringRequest(....);
stringReq.setShouldCache(false);
2) Deleting cache for particular URL : Use remove() to delete cache of an URL.
yourRequestQueue.getCache().remove(url);
3) Deleting all the cache :
yourRequestQueue.getCache().clear(url);
Also, check out this link here.
Hope this helps.
So to belatedly answer my own question. I ended up taking a different approach to ensure that I always get the latest copy of an avatar image and it turned out to be very simple.
Instead of trying to clear out an individual image from the cache I use the following method.
int time = (int) (System.currentTimeMillis());//gets the current time in milliseconds
String myUrl = "www.mySite.com?timestamp=" + String.ValueOf(time);
profileImg.setImageUrl("myUrl", mImageLoader);
What this does is to append an imaginary parameter to the url I call to get the image with a current timestamp. This guarantees that I am always making a call to a unique url and so therefore am always getting the most up-to-date version of that image.
The beauty of this approach is that it is not limited to Volley and can be used however you choose to make network calls.
in the LruBitmapCache you should do diable put(url, bitmap) :
#Override
public void putBitmap(String url, Bitmap bitmap) {
// put(url, bitmap);
}
by this way every time you call the volley method image don't save to catch
To turn off the cache:
1
request.setShouldCache(false);
to remove the cache for a specific request:
1
queue.getCache().remove(url);
to clear all cache:
1
queue.getCache().clear();
to invalidate the cache: this will allow to display the cached data until the response is received. When the response is received, it will automatically override the cached data.
1
queue.getCache().invalidate(url, true);
for more details you can refer to the
url:http://androidresearch.wordpress.com/2014/02/01/android-volley-tutorial/
If you create the cache like this:
RequestQueue requests = Volley.newRequestQueue( context );
BitmapCache cache = new BitmapCache(cacheSize);
ImageLoader loader = new ImageLoader( requests, cache );
You can clear all like this:
public void clear () {
cache.evictAll();
requests.getCache().clear();
}
I have created volleySingleton Class. I load image from ImageLoader . I have a requirement of deleting the cache but not able do that. Used all these three method
1) Deleting cache for particular URL : Use remove() to delete cache of an URL.
VolleySingleton.getInstance().getRequestQueue().getCache().remove(ImageUrl);
2) Deleting all the cache :
VolleySingleton.getInstance().getRequestQueue().getCache().clear();
3)
VolleySingleton.getInstance().getRequestQueue().getCache().invalidate(ImageUrl,true);
I have tried all of them but cashe is not getting deleted