I'm using Picasso to initially download images of products to my app from a server. Since the images aren't changing nearly at all for a certain product, I save the images to the disk from the ImageView. In the app I have to display these images all over again in different sizes. To do so I'm using Picasso again, loading the saved file into an ImageView and do fit().centercrop() so I don't get any OutofMemory issues.
Since Picasso is also capable of using OkHttp's cache and doing the caching by its own, I want to know:
Are there any advantages about letting Picasso do the caching, over saving it to storage manually and handing it over again to Picasso later?
And would it be a good way to store the shrinked image (after using .fit()) as a new file so the calculation hasn't to be done all the time.
Related
in my recent android project I have to get a large number of images from the web and show them in my main activity (something like explore part of the Instagram app). I used a recyclerView with gridLayoutManager of 3 columns and I have to get something like 700 images from URL. When I open the app and comment the getting image part, app work perfectly fine (the app get the information of each tile but doesn't display the images). But when I start setting image bitmaps the app start becoming laggy and crash after about a hundred images loaded.
What do you recommend me to do ?
And another question: Was using recyclerView a smart idea ?
Thanks for your reply.
Don't load hundreds of images. That requires a few things:
1)Don't store images in memory in the adapter. Store the url/resourceid/whatever of the image so you can load it on demand.
2)Use an LRU cache of images, limited in size and load your images through that.
3)Make sure that however you download images does not spawn too many concurrent requests, and that requests are canceled when no longer needed (when the view it would go into is recycled).
4)I'd suggest downloading the images and writing them to disk, then loading them from disk as needed. This will prevent you from having to keep the entire file in memory to decode it while downloading it, which will reduce your memory usage while downloading.
5)Do not decode the image on the UI thread. Do it on another thread.
6)If you don't need to display images fullsize, make thumbnails.
Images in a RecyclerView, especially if being downloaded need a lot of work to do well and handle rapid scrolling.
You should post some code here but seems you are asking for some efficient setup.
First of all, try using some image caching libraries like Glide or
Picasso. It manages and caches your images locally so you don't end up
making multiple requests for the same image.
This solves most of your problem and don't try to load 700 images
altogether and display use lazy loading means load first 10-20 images
first and when user scrolls make another API call for another 10-20
and so on.
Here is an article on how to use Glide and how it works.
https://futurestud.io/tutorials/glide-image-resizing-scaling
I am loading multiple images locally from devices storage. I am currently using Glide to load them. But Glide is very big library and it offers many features which I don't need at all, for ex. disk cache and loading from internet. Is there any better and more efficient library or another way to load images from devices storage?
The only functionality I need is memory bitmap cache, async loading from Uri and resizing just like in Glide.
You can use Picasso, its method count is ~700 compared to ~3200 of Glide, you can save lots of method count here.
I will recommend you do keep using image library, it does lots of cool stuff in the background, which requires lots of dev efforts.
Resizing of images according to view size
Caching in memory using LRU cache
Recycling of Bitmaps to free up heap once you are done with displaying
Disk cache, so that you can load faster on app restart OR eviction from LRU cache
Proven record of working on fragmented Android ecosystem
No need to take care of threads, thread pools
Also on top of if you are using Proguard (using minifyEnabled true in your build.gradle ) for code obfuscation, it will strip away methods which are not getting used in your apk
I have a question about mechanisms used by Picasso for downloading and caching images.
How does Picasso download an image? I know that it is using in sample size. Am I right? If image on a server is 1000x1000 but ImageView is only 400x400 then it will be download only 500x500 image and it will be cached. Or maybe it will be downloaded in full resolution and then scaled to a specific size.
Here is actual code I am - and I'm sure many more people are - using
Picasso.with(context).load(url).fit().centerCrop().into(imageView);
Picasso has no way of knowing it should download only 500*500 pixels. The fit() and centercrop() methods will make it fit even when picture is bigger than needed.
You can browse source-code of Picasso at: https://github.com/square/picasso.
Downloading images
You can see that Picasso downloads images with implementation of Downloader interface. It uses default downloader named OkHttpDownloader, which utilizes OkHttp library. When it can't be loaded, Picasso uses UrlConnectionDownloader.
Recognizing size of the images
Picasso doesn't know size of the images before download. If you are developing back-end server, you can specify size of the images in some way, so your mobile application will know it by performing a concrete request, but it can't be recognized by Picasso itself. Picasso has to download image in a full size and then this image can be cropped or resized by this library.
Cache
We can find the following information about Cache in the Picasso documentation placed in source code:
Picasso instance is automatically initialized with defaults that are
suitable to most implementations.
LRU memory cache of 15% the available application RAM
Disk cache of 2% storage space up to 50MB but no less than 5MB. (Note: this is only available on API 14+ or if you are using
a standalone library that provides a disk cache on all API levels like
OkHttp)
Three download threads for disk and network access.
It explains usage of cache in this library quite clearly.
I'm just not sure, if Picasso stores images before transformation (resizing, cropping, etc.) or after transformation in cache. First option seems more reasonable for me, because we decide to apply a different transformation later, so we may want to keep original image.
I have an app where people can set pictures as wallpaper but its really slow because pictures are very big. This app load pictures and then when i want to see it again it has to load again.
What to do to make it faster? I use Json service. My pictures are from server. i am using universal image loader.
Theres 2 types of cache in android, the memory cache and the disk cache. You should use picasso its a library that implement both and is very easy to use (1 line of code).
I am using picasso library for loading images .In default picasso, It uses internal cache memory for loading images.But as per my app configuration ,i have to use external cache memory(Cache on Disk).
so i used this code for Cache on Disk
File httpCacheDir = new File(getApplicationContext().getExternalCacheDir(),"http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);}
Picasso is flexible. So now it caches images in external Sd card..
The caches is stored in sdcard/android/data/packagename/cache/http
The caches are stored in ".1" ,".0". formats
so i just opened them and changes into ".1" to ".jpg".it gives exact images what i need.
But how to do in programatically? but picasso itself caches my memory in to my app for loading image into imageview.but i have to save them into sdcard directly as images/set bitmap as wallpaper in offline mode?
You can supply your own Cache implementation when building your Picasso instance. This way you can provide extra methods that you can call to retrieve bitmaps directly from your memory cache. Use Picasso.Builder to provide your own implementation for it. When you use with() you are using a static singleton internal instance thats setup with most of the default values (most apps need the default values anyway.)
Keep a reference of your Cache implementation around and directly interact with it. Picasso is meant to handle the loading/decoding and caching for you but there is no reason you cant build around it.
If you are referring about the disk cache, then no Picasso does not support that at the moment. This is by design because the disk layer cache is done by the HTTP layer and makes no distinction about it.
You could however, change the path of the disk cache. If you are using OkHttpDownloader then supply a different file when you construct your Downloader. Similarly for UrlConnectionDownloader you could extend it and override the load() method.
Picasso does handle the caching in it and downloading also you just need to place it in your target Image view similar to Aquery
According to The Corner Square Engineering blog
picasso handle downloading caching in it self and give its handler to user to use it and place the image in image view