I have around 200 images as vector drawables (in res folder) that i'd like to load in recyclerview. Since the size of vector drawable is not that big I've decided to store them inside the app and not set up the server or do api call. The total size of 200 images sums to 4/5 MB only. When I try to show the images in recyclerview it's creating a lag. Since Picasso and Glide are no use for vector drawables what approach would be the best to solve the lag issue? Is paging helpful for local resources?
The lag is because of the decoding of the vector into bitmap on the UI thread. You can read it here https://developer.android.com/reference/android/widget/ImageView.html#setImageResource
Quick solution would be to use any image loading library like Glide which does this stuff in background.
You can use pagination to avoid the lagging of the images while loading. It will be so fast even the app lifecycle is stopped or destroyed.
Android Paging Docs
The Paging Library helps you load and display small chunks of data at a time. Loading partial data on demand reduces usage of network bandwidth and system resources.
Here is the docs for Paging using RecyclerView
I hope it works for you.
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'm creating an Android app. For this I created a recyclerview, which gets filled by images and texts. Until now I've got the images from my server with sockets and byte[]. In my app I converted this to bitmaps. But that has not the best performance. Should I get the images with Picasso and URL? Has this a better performance?
Generally in the android or iOS app from the API's we have to get the image url. By using image loader library's we will load that data.
For the android most of the developers prefer universal image loader or picasso for loading their images.
It is best to rely on image loader library like Picasso or UniversalIL as these libraries will manage caching, downsampling and even error handling. Android is very sensitive about bitmap. Without proper management, there will be a lot of exception including the infamous one: BitmapOutOfMemory.
There are 3 locations where images are stored. Their comparison on Memory space availability and Accessibility speed is given below:
Server (Memory Space is HIGH but Accessibility is SLOW)
Hard Disk on Mobile (Memory Space is MEDIUM and Accessibility is MEDIUM)
Heap Memory (Memory Space is LOW and Accessibility is FAST)
We need to create a balance among above 3 locations for optimum utilization of accessibility and memory space.
Use any lazy loading library like picasso or UIL and you don't have to worry about any of these points.It will handle everything itself :)
I am loading images in a recyclerView using picasso in my app. The image files are all local files. The problem is that the listview scrolling is not smooth, it is jittery. I searched about it and I saw that a lot of people have had similar problems but it is really strange that there is no clear solution available.
Horrible performance when loading local files
Picasso is awesome, but for loading local device images as thumbnails into a gridview (for example), Picasso is slower ...
Recyclerview painfully slow to load cached images form Picasso
From the above links it seems that picasso works great when fetching images from the web but for locally stored images it doesn't do that great.
Is it even recommended to use Picasso in this case? Should I have my own implementation of LruCache and remove Picasso? I have done it without Picasso using caching myself using LruCache. Though the scrolling is flawless in that case but Picasso is much more clean and compact, so I thought it might be the better solution in the long term.
There could a lot of reasons for this kind of behaviour. One issue could be that your row layout may be very deep rather than being wide. Another issue could be the size of images, if images are of large size, there is a good chance that all of them might not fit into Picasso's cache.
If the problem is due to the size of images, you can try Fresco by Facebook. It is very good at loading large images. It uses native as well as ashmem cache, so it can hold large amounts of images in cache compared to other similar libraries like Picasso or Glide. Another thing you can do is, android:largeHeap="true" in your AndroidManifest.xml inside the Application tag.
I am looking for an asynchronous image loading and caching library in Android. I was going to use Picasso, but I found Universal Image Loader is more popular on GitHub. Does anyone know about these two libraries? A summary of pros and cons would be great.
(All my images are on disk locally, so I don't need networking, therefore I don't think Volley is a fit)
Update Sep 2018: After several years, I needed the almost same thing for a local image caching solution. This time around, UIL has not been in active development. I compared the popular libraries, and the conclusion is pretty no-brainer: just use Glide. It's much more powerful and configurable. Years ago I had to fork and make changes to UIL. Glide supports all my use cases in terms of caching strategy and multiple levels of resolution caching with custom keys. Just use Glide!
Koushik Dutta's comparison is mostly for speed benchmark. His post only touched very basic things, and is not specific for local images. I'd like to share my experiences with Picasso and UIL after I asked the question. Both Picasso and UIL can load local images. I first tried Picasso and was happy, but later I decided to switch to UIL for more customization options.
Picasso:
Picasso's fluent interface is nice. But jumping around with "with", "into", "load" you actually don't know what's behind the scene. It's confusing what's returned.
Picasso allows you to specify exact target size. It's useful when you have memory pressure or performance issues, you can trade off some image quality for speed.
Images are cached with size in its key, it's useful when you display images with different sizes.
You can customize the memory cache size. But its disc cache is only for http requests. For local images, if you care about loading speed, it's good to have a thumbnail disk cache so you don't have to read several MBs for an image every time. Picasso does not have this mechanism resizing and saving thumbnails on disk.
Picasso does not expose the access to its cache instance. (You can get a hold of it when you first configure Picasso and keep it around...).
Sometimes you want to asynchronously read image into a bitmap returned by a listener. Surprisingly Picasso doesn't have that. "fetch()" dose not pass back anything. "get()" is for synchronously read, and "load()" is for asynchronously draw a view.
Picasso only has a few simple examples on the homepage, and you'll have to read through the unordered javadoc for advanced usages.
UIL:
UIL uses builders for customization. Almost everything can be configured.
UIL does not allow you to specify the size you want to load into a view. It uses some rules based on the size of the view. It's not as flexible as Picasso. I have no way to load a lower resolution image to reduce memory footprint. (Edit: this behavior can be easily modified by adding an ImageSize argument in in the source code and bypass the view size checking)
UIL provides customizable disc cache, you can use this to cache the thumbnails with specified size. But it's not perfect. Here are the details. (Edit: if you care about speed and want multiple levels of thumbnail caching, like my case, you can modify the source code, let the disk cache use "memoryKey", and make it also size sensitive)
UIL by default caches images of different sizes in memory, and it can be turned off in configuration.
UIL exposes the backing memory and disk cache you can access.
UIL provides flexible ways you can get a bitmap or load to a view.
UIL is better in documentation. UIL gives the detailed usages on the Github page, and there's a linked tutorial.
I suggest starting with Picasso, if you need more control and customization, go for UIL.
If you read this post on G+ by Koush you will get clear solutions for your confusions, I have put the summary of that, in that Android-Universal-Image-Loader is the winner for your requirement!
Picasso has the nicest image API if you are using network!
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(if you are using network)
Android-Universal-Image-Loader is the most popular one out there
currently. Highly customizable.
This project aims to provide a reusable instrument for asynchronous
image loading, caching and displaying. It is originally based on Fedor
Vlasov's project and has been vastly refactored and improved since
then.
Upcoming changes in new UIL version (1.9.2):
Possibility to call ImageLoader out of UI threadNew Disk Cache API
(more flexible). New LruDiscCache based on Jake Wharton's
DiskLruCache.
Considering all this Android-Universal-Image-Loader suites your requirement (Loading the images are on disk locally)!
I would like to share my experience with these 3 libraries: UIL, Picasso and Volley. I previously used UIL but then I came to the conclusion I can't really recommend it and I would suggest to use Volley or Picasso instead which are both developed by highly talented teams. UIL is not bad at all but it lacks the attention to detail of the other two libraries.
I found UIL being less nice with the UI performance; it tends to lock up the UI thread more than Volley or Picasso. This may be in part due to the fact that UIL does not support batching the image responses while Picasso and Volley do that by default.
Also, I didn't like the disk cache system of UIL. While you can choose between various implementations, I need to point out that at the moment there is no way to limit the UIL disk cache both by total size and by entity expiration time. Volley and Picasso do that, and they use the expiration time returned by the server by default while UIL ignores it.
Finally, UIL allows you to set a global image loader configuration which includes the selected disk cache and memory cache implementations and settings and other details, but this configuration will be applied everywhere in your app. So if you need more flexibility like two separate disk caches, it's a no go for UIL. Volley on the other hand allows you to have as many separate image loaders as you want, each with its own configuration. Picasso uses a global instance by default but also allows you to build separately configurable instances.
To sum it up: Picasso has the best API but it uses the global HTTP disk cache shared between all HttpURLConnection instances, which can be too restrictive in some cases. Volley has the best performance and modularity but is less user friendly and will require that you write a module or two of your own to make it work like you want. Overall I would recommend them both against UIL.
Edit (Dec 18 2014): Things have changed since I wrote this initial answer and I felt it was necessary to improve it:
Picasso 2.4 is even more configurable than older releases, and when used with OkHttp (which is highly recommended) it is also able to use a separate disk cache for each instance so there is really no restriction in what you can do.
More importantly, I noticed that the performance of Picasso and OkHttp has improved a lot and in my opinion it's now the fastest image loader solution for Android, period. Please note that in my code I always use .fit() in combination with .centerCrop() or .centerInside() to lower memory usage and avoid bitmap resizes on the UI thread. Picasso is actively developed and supported and that's certainly a big plus.
Volley hasn't changed that much but I noticed two issues with it in the meantime:
Sometimes under heavy load, some images are not loaded any more because of some disk cache corruption.
Thumbnails displayed in a NetworkImageView (with its scale type set to centerCrop) are quite blurry compared to what you get with the other libraries.
For these reasons I decided to stop using Volley.
UIL is still slow (especially the disk cache) and its API has a tendency to change quite often.
I also tested this new library called Glide 3 which claims to be more optimized than Picasso with a Picasso-like API. According to my personal experience it's actually slower than Picasso and Volley during network requests under heavy load, even when used in combination with OkHttp. Worse, it caused a few crashes with my apps under Lollipop when leaving an activity. It still has 2 advantages over its competitors:
It supports animated GIFs decoding
It puts the final downscaled bitmaps in the disk cache, which means reading back from the disk cache is extremely fast.
Conclusion: I now recommend to use Picasso + OkHttp because it provides the best flexibility, API, performance and stability combined. If you need GIF support you can also consider Glide.
I have implemented an app that should constantly get and show images from the internet. I was about to program an image cache mechanism, before that a friend recommended me the universal image loader.
The UIL is very good customizable. It's so customizable that a newbie can easily make something wrong. However, the UIL was slow in my application and it became a bit slower. My use case was a ListView with images.
Yesterday I was looking for an alternative to the UIL, and I discovered Picasso. Picasso was easy to integrate and to use: Just Picasso.context(context).load(url).into(imageview) and the image could be faster and smoothly be integrated.
For me, Picasso is definitely the API to use. My experience with UIL wasn't good.
I think ImageLoader is more customizable and flexible comparing to Picasso library.
Hi and happy new year!
I'm trying to download images from internet and put them into different ImageViews. The ImageViews are dynamically created as the user scrolls. When user arrives to the bottom of the scrollview, I load 10 images more.
The images are loading ok, but when i have a lot of images I get a java.lang.OutOfMemoryError.
I know the problem is that I have a lot of images consuming a lot of memory, so... what's the way to go on my scenario?
Thanks!
Try using a ListView instead of a ScrollView. Then you can use a lazy loading technique like Universal Image Loader. The ListView utilizes view recycling which will be easier on your memory, and you can also cache images using the image loader. This library also has a few options for memory management as well.
You are going to have to keep track of the images you have loaded and start recycling them when they are out of view.
You might find the LruCache a valuable tool. There was a good talk at IO12 "Doing More With Less: Being a Good Android Citizen" that went over lots of memory issues and includes some discussion on how to use the LruCache starting around the 4 minute mark.