Users can change a picture (replace it). Once the user changes their image, I want the new image to get cached in Glide and the old image to get thrown out of the cache.
I've read everything online but I'm still at a loss on how to implement a good solution to this.
I've tried skipping the local memory and disk caches like when setting the image:
GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(view);
This solution is SLOW because it now calls the new image every single time - it never caches the new image.
Glide documentation says:
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://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
But that is not possible for me, so Glide documentation then says:
Since it’s often difficult or impossible to change identifiers, Glide
also offers the signature() API to mix in additional data that you
control into your cache key.
And it gives this example:
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new ObjectKey(yourVersionMetadata))
.into(yourImageView);
But here comes the issue. What would be a good "yourVersionMetadata"? How do I create and maintain it? I've seen examples like so:
.signature(new ObjectKey(Long.toString(System.currentTimeMillis())))
This causes the disk cache key to change every time I load the image, so it is SLOW. I just need it to change when the user replaces the image. Not every time the image loads.
Someone wrote:
You can do something like generate a new UUID or increment an integer whenever the image changes. If you go that route, you'll have to keep track of the current signature for each image somewhere. - https://github.com/bumptech/glide/issues/2841
I don't understand how to do this.
I also tried the Async task for completely deleting cache. It works, but again it's super slow (and Glide doesn't recommend using this approach).
I don't know how I can just insert the current signature (which should be faster) rather than creating a new signature every time the image loads. Help? It seems to replace an image and recaching it shouldn't be so difficult!
I worked on this for days.
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, and I successfully implemented them too. But to me, they seemed just as slow as skipping cache entirely.
Two options
1) To generate a unique signature for a file you can calculate the MD5 signature for it. It will always be unique for a file until it is modified. See how to generate the MD5 signature here.
2) Another way to set a unique signature could be using the last modified time of the file. If you are sure that only your app will be modifying the image and nothing else then you can also rely on this. To get the last modified time use:
File file = new File("path/to/image");
String signature = Long.toString(file.lastModified());
Related
I'm new to caching and stuff. I have an app that fetches images from firebase storage by their url using Glide. Now it will cost me a lot if the user fetches a single image "every time" they use the app using the url (also a single image might be visible in couple of activities , so then fetching becomes redundant). So does glide cache is valid even after app restart and across all the activities or is it activity related( I mean for every activity does it has separate cache or is it just simply dependent on the url)?
Also is the caching enabled by default?
Sorry if the question sounds stupid, but otherwise the cost will increase significantly. Thanks.
Yes it's store some cache after app restart also the best way to invalidate a cache file is to change your identifier when the content changes (url, uri, file path etc) when possible.
My overall object is to delete certain type of images (which are temporary) after a certain period like after one month, from disk cache of the my app.
I'm using Glide, so I know that using Glide, I can clear entire disk Cache but my goal is to clear only a certain type of images from disk cache. Like for example, live banner images from my app (which keeps changing after certain period). Problem is, they keeps adding space even though one gets inactive. So ideally I should delete all old banner images from cache.
What I'm thinking is have a separate Glide Module just for these banner images and setup a different internal cache directory for these images, and after a month, ask Glide to delete/clear this directory.
Another thing is to use Glide's signature concept which invalidates the images.
For both of above ideas, my problem and question is that I want to use only for certain type of images but more I read about them, it feels like once I use them, they apply to all images being download using Glide
Even if I use multiple Glide module, they all gets used for all the images (that's why there is a concept of conflict management for glide modules)
I might be wrong, and there might be indeed a way to get a solution to my problem. All I need is your help if you know a way :)
I'm aware that if nothing works out for my solution, then to keep my app's size impact low, I'll have to decreased overall internal disk cache size which is 250MB by default.
Thanks.
I have simple caching problem:
I have old "name.jpg", then customer uploads new "name.jpg" and clients dont see any changes, for them its still cached old "name.jpg".
I know how to turn off caching, but its not good decision, so I try to find better.
So question is:
How does caching work if I add get parameter after question mark?
For example I have url
http://example.com/name.jpg?cache_time=111
And then I replace it to
http://example.com/name.jpg?cache_time=222
Will it download second name.jpg and replace existing or not? I know its work with css or js files in browser, but know nothing about glide behaviour.
Whatever parameters you pass in the url query will be sent to the server serving the image and only if that server handles that exact parameter (cache_time) can there be any difference in behavior.
The caching glide does however is not based on what you send to the server, but rather on the configuration you give to glide.
I suggest you look up how glide handles caching, and perhaps manually invalidate the cache for a specific image when you know it has changed.
This is a good place to start: Remove image from cache in Glide library. It also has examples how to use signature()that is mentioned in the comment above.
I need to access an image that has been cached after it has been transformed (or cropped) using Picasso.
What I am doing is taking a large image resource, cropping a screen-size piece of it out of it at run-time, and setting it to the background of a RelativeLayout. So far I have used Picasso to accomplish this successfully.
Later in the app, I change the app layout by calling:
setContentView(R.layout.OTHER_LAYOUT);
I would like to then access the cache where Picasso stored the cropped version of the image, and dynamically set the background of OTHER_LAYOUT to the stored version of the cropped image.
This S.O. post seems relevant to accessing a bitmap cached by Picasso on device.
I am considering giving this solution a try. But one user's comment (a comment on the accepted answer) makes me wonder if there is a better way. Complicated solutions often seem more bug-prone.
"it seems can work. but in my opinion, it is not well offer. files are being saved somewhere. lib should give them to developers. it would be good instead of adding millions feature to picasso lib, adding very simple and essential features. I gave up to use picasso because of this. It has millions garbage features and very limited nice features."
Is there some way that Picasso allows me to access the image that was transformed and cached, and use it somewhere else (in a way that is simple & easy to use)?
If not, would another library give me greater convenience?
Don't think too much about reusing cached images, Picasso is very good at that and is well optimized for it. Just load the same URL / drawable and apply the transformation. If Picasso already cached it, it will be very fast, you can check if it is cached by setIndicatorsEnabled(true) on Picasso instance.
I'm making an android app, here the images are getting from Cloud, is it good idea to download images and save it & use it further. Or download images every-time user uses the app, what idea you prefer is the best?
Because downloading images always is slow & its bad i know but at some point if the images are updated then how to get to know about it?
You should definitely cache your downloaded files!
Do it in your internal app directory where only you do have access to (or otherwise external storage, thats still ok).
Bandwidth and connections are always expensive and should kept low as much as possible.
So your user can see images fast even on a bad connection and your app doesn't waste his valuable bandwidth of a users data plan.
Maybe this could also help you:
https://github.com/novoda/ImageLoader
http://www.androidhive.info/2012/07/android-loading-image-from-url-http/
Make it easy on yourself and use something like Android Smart Image View. It takes care of loading and caching, and it's just about a drop-in replacement for Android's ImageView. Universal Image Loader is another alternative, more configurable, but not as quick to implement.
I used https://github.com/nostra13/Android-Universal-Image-Loader
but I think you not want only download and cache.
these no trick ,if you want check weather the image update or not, you can add metadata for image, just like md5 .
in html and browser, you can set expires header for a image:
enter link description here
but in android app, you control all yourself.
Downloading images and saving them is probably the best way to do it because you don't want to download the same images over and over. If the images are updated you can delete the older one and download the new ones. Just make sure you don't download/save a million images. Take a look at this library. It has a built-in cache on sdcard/external sd.
Downloading images from the net for display, with possible requirement of caching is a very common problem that many people have solved, you can try these solutions to see which fits you:
Ion (https://github.com/koush/ion) - very flexible and feature complete, plus it can download more than images but JSON, Strings, Files, and Java types as well. The part that I really like about this is that it can automatically cancel operations when the calling Activity finishes, so users don't waste time & bandwidth downloading images that will no longer be displayed
Universal Image Loader (https://github.com/nostra13/Android-Universal-Image-Loader) - equally capable for most use cases but for downloading/caching images only