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.
Related
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());
I am trying to figure out the best and the most efficient way of caching images to the disk, such that they would persist even after app is killed and re-launched in airplane mode. Consider the following use case:
Open the app and get all images and display them in their respective ImageView's
Kill the app
Put device in air plane mode
Open the app again.
I am trying to get the images to persist in an offline cache so that they can be displayed in the scenario mentioned above.
I went through documentation for picasso and glide and it wasn't exactly clear if their disk caching would work in this case.
Is there a way to do this using picasso or glide? I am trying to avoid having to write a custom implementation for storing this in SQLite etc.
Glide will do this for you by default without any extra work on your side. You can also customize what versions of the requested image to store in the cache.
One important thing you need to consider is if the URLs that you use Glide to fetch images from are available offline otherwise you will need to have some way to cache those as well so that you can initiate the Glide calls when you are offline.
You can see how I did it in this project: https://github.com/KhalafMH/popular-movies-android.git
To read about how to configure Glide caching see:
http://bumptech.github.io/glide/doc/caching.html
I am very new to Android. I am trying to create a social app which contains lot of images and some metadata. It has a screen which is similar to the feed on Facebook. I want to make this screen as smooth and standard as possible.
Here are the libraries I am using: OkHttp, Picasso, Retrofit, Gson.
Right now, I am fetching all the json in one go, since I have seeded dummy values in backend and the response is small enough. But, in future, it will have the previous and next fields to limit the json response.
Some of the questions that I have right now:
I am using Picasso with OkHttp. Does that cache images in disk too or only in memory?
What are the best practices on caching the feed? Since the majority of content is images, should I just let Picasso handle the caching or should I cache some items on my own? Heard about DiskLruCache library from JakeWharton but not tried it. Should I go with it?
How to keep some feed contents(like 3 or 4) in either direction of scroll in cache so that scrolling appears smooth and that images don't start loading after coming in the view.
How to automatically handle json response using previous and next fields when the user scrolls all the content that was fetched in this one go. Basically I want to trigger requests based on the number of contents scrolled based on cursors.
Suppose there is a like button and the user click it, should I change the number of likes in the UI and side by send a POST request to update counter or should I send the request and wait for the updated counter from server before updating it in the UI?
I have already gone through the source code of Instamaterial and got to learn some amazing things. But it does not demonstrates the whole backend integration.
I just want to know if there are any other open source apps which I can study or learn from. If you know any tutorials that would help too. I just want to make the app experience as smooth as possible and want to learn some best practices.
This will cache to disk as well as memory. If you set Picasso to debug mode it will display an indicator that describes where the image was loaded from (memory/disk/network)
If you don't mind Picasso having control over how long things are cached etc. then it should be fine to let it handle the caching. I'm also pretty sure that Picasso uses DiskLruCache
If your main concern here is the images, they will all be cached and shouldn't need to load after they have done so once (until it updates). You can also register a callback with Picasso in order to change the logic around showing or hiding placeholders.
I think that what you are looking for is a scroll listener on your listview (I assume you are using a list view). When it gets past a certain position (5/6) start loading the next 10. If you are using a recyclerview you can do this with the onScrollStateChanged function in the scroll listener and use the LinearLayoutManagerto call findLastVisibleItemPosition
It shouldn't really matter which approach you go with. If you think that it will take a long time for it to update the server counter (which it shouldn't) then it is probably best to update it locally first.
1.I would suggest you to checkout Image Management Library by Facebook that is Fresco that is pretty awesome and mature as compared to other Image Loading Library.
2.Fresco handles all the things caching of images with 3 Tier architecture ( BITMAP_MEMORY_CACHE, ENCODED_MEMORY_CACHE and DISK_CACHE). It also reduces OOM(Out Of Memory) issues. When image in a view goes out of screen it automatically recycles the bitmap, hence releasing the memory.
3.For that you have implement Pagination, yeah for sure you might have to send the previous record item position or index, so that you can fetch the items succeeding it.
4.For providing user the smooth experience in your app, you should increment the counter and send the post request to your backend simultaneously.
you can also checkout this tutorial Facebook like Feed.
I would prefer you some approaches for some of your questions:
For handling JSON:
You can use library called Retrofit, so adding and removing stuff in server side, will be easy to handle in your android client side. Just removing or adding variable in a Java class will be enough!
For cashing images:
I suggest you to use Fresco, facebook library, It will ease your job alot. since it can handle rounded corner conversions, downloading Progress bars, Circular images and many more features. So, Not only handle the Memory and Disk cashing for you, but also works better with different image formats.
(I used picasso in my last project, Some pictures and some URIs did not work well, I tried Picasso, Glide, and Universal Image Loader, on exactly same image and same link..ONLY Fresco could work fine for me)
It is not exactly answer to your questions, however, i wanted to share my experience with those libraries that may help you.
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 looking for an open source image loading/caching solution.
I am looking in to:
Google's Volley,
Square's Picasso
Universal Image Loader
I want to be able to handle async image loads from disk as well as network, however I'm not sure if Google's volley handle's loading from disk.
Does Volley allow resource loading from disk??
An example of what I would like to do is available with AQuery.
If you're ok with newer/less stable software, I just released an open source library called Glide: https://github.com/bumptech/glide
It's designed to allow you to efficiently load any image you can get an InputStream to. It includes some basic http/file loading implementations, but also allows you to plug in your own or use some external library (like Volley) via callbacks.
It includes memory and disk caching, as well as bitmap recycling on newer devices. All you need to do is implement an interface to get an input stream for your data model (path/url/uri etc) and pass it along with whatever transformations, placeholders, or animations you want to the Glide singleton.
Happy to speak with you or anyone who is curious, we've used it extensively at Bump to interface with a variety of libraries.
I have collected few important information from http://blog.bignerdranch.com/3177-solving-the-android-image-loading-problem-volley-vs-picasso/
(the comparison between older ver Picasso 2.0 vs volley)
Picasso is totally focused on image loading. As a result, if you have
quirks in your image loading process
Volley, on the other hand, is totally focused on handling individual,
small HTTP requests. So if your HTTP request handling has some quirks,
Volley probably has a hook for you. If, on the other hand, you have a
quirk in your image handling, the only real hook you have is
ImageCache. It’s not nothing, but it’s not a lot, either.but it have
more other advantages like Once you define your requests, using them
from within a fragment or activity is painless. And unlike parallel
AsyncTasks
Picasso does just one thing, while Volley tries to solve a more
general problem.
Android does not handle high-res images well at all. I have a small
obsession with the pattern of catching OutOfMemoryError in Android
apps. It seems like a ridiculous tactic, but Volley is the only way
to reliably handle some image scenarios compare to hassle with
Picasso's scaling and fitting big images correctly. Picasso doesn’t
respect the scaleType attribute on your ImageViews(not sure it's is
fixed in latest ver).
Test Ex: I found that Volley catches OutOfMemoryError while loading
the original resolution image instead of the thumbnail version,
comparing to the Picasso version doesn’t blow up (it catches
OutOfMemoryError, too), but picasso fails to load any images that are
too large. Not only does Volley not blow up, but Volley displays all
these large images!!!.
According to Android Hacker Koushik Dutta:
Testing ALL the Android Image and http Libraries
I've been testing and benchmarking a bunch of the various image
loading and http request libraries available, since a couple of them
were released in the past week.
Lineup:
AndroidAsync + UrlImageViewHelper (koush)
Volley (Google)
okhttp + Picasso (Square)
All support cached and conditionally cached responses, keep alive,
etc.
Thoughts:
Picasso has the nicest image API. I am going to steal their currying API style for my future/current stuff. Picasso is also
noticeably the slowest. Especially on 3g vs wifi. Probably due to
their custom okhttp client.
UrlImageViewHelper + AndroidAsync is the fastest. Playing with these other two great libraries have really highlighted that the
image API is quite dated, however.
Volley is slick; I really enjoy their pluggable backend transports, and may end up dropping AndroidAsync in there. The request priority
and cancellation management is great.
Update These aren't really http libs. Just image loaders. but there
were requests for comparisons in the comments...
Android-Universal-Image-Loader is the most popular one out there
currently. Highly customizable.
AQuery; like jquery, but for Android? I guess it's nice, if you're
into that sort of thing. Don't use this one though; it craps on the UI
thread or something. Loading a bunch of images on my Nexus 4 in a
listview made it seem like I was back on my HTC G1 all over again.
Major stuttering.
Tests with caches clear:
Cold is fresh app start. Warm is caches clear with http connections
presumably kept alive.
Cold/Warm (in milliseconds, avg of 10 runs, clearing data every run):
Picasso 12142/11892
UrlImage 7378/4525
Volley 8292/7520
Android-Universal-Image-Loader 14484/11243
AQuery 11341/9637 (this one seems to lock up the UI thread... don't use it)
Here's the test code base:
https://github.com/koush/AndroidNetworkBench
Conclusion: These tests are hardly conclusive. I just tested concurrent network access with many images. Admittedly, there's more
to testing a library than that. I like how Volley plays nice with the
Activity lifecycle, for example. None of the other libraries do that.
So, whatever floats your boat really. I(Koush) want Volley with
Picasso's API.
volley' Request class deal with all network requests. I have not yet found any class loading resource from disk..
Out of the box Volley does not include its own disk cache implementation. You need to take a DiskLruCache (or a hybrid memory/disk cache if you prefer) and have it implement the Volley ImageCache interface.
This blog post sums up how to implement a disk based cache with Volley to load images: http://blogs.captechconsulting.com/blog/raymond-robinson/google-io-2013-volley-image-cache-tutorial .
Just use Picasso library :
Picasso.get()
.load("/images/oprah_bees.gif")
.resize(50, 50)
.centerCrop()
.into(imageView)
This will allow you to load specific file from SD and you can pass the imageView too where u can set this image.
To Read more feature into Picasso Library
Volly can also be used to load files on disk.
Use:
networkImageView.setImageUrl(Uri.fromFile(newFile(filename)).toString(),mImageFetcher);