I have a ListView with many lines (about 200).
In each item of the ListView there is a thumbnail picture.
The pictures are downloaded for form the internet as the ListView scrolls.
The problem is that if I scroll rapidly the ListView it gets sluggish and quickly I get an Out of Memory error.
Please could you suggest an approach on how to avoid this?
Use View Holder pattern on the custom adapter you're using with lazy loading.
Lazy Loading using Universal Image Loader.
OR
you could give Picasso / Volley Libraries a shot. They can handle caching efficiently for you.
The basic flow is to use a caching system:
Download Image to your cache directory -> read it back into memory cache -> scale it down (if the image is larger than the the image view that displays it) -> display it in your image view.
The official android training has a great tutorial along with full source code on how to create something like this.
They address the common issue of scrolling lag by pausing the background task(s) while user is scrolling.
Out Of memory is addressed through LruCache.
Alternatively you can use a third party library like the Universal Image Loader for addressing this issue.
You must handle your view recycling. It's a very important performance issue and you should always handle it.
See this post, it will guide you in this process, handling the view recycling and using the View Holder pattern. Also see this.
There are many reasons for recycling views:
Object creation is relatively expensive. Every additional object that is created needs to be dealt with by the garbage collection system, and at least temporarily increases your memory footprint;
This is more important for more complex views, but inflating and laying out the view objects can be expensive. Most often, you are only making minor changes to the view in getView that won't affect the layout (e.g, setting text) so you might be able to avoid the layout overhead;
Remember that android is designed to be run in a resource constrained environment;
Finally, its already done for you, and it certainly doesn't hurt anything, so why not use it;
Hoe it helps you.
Related
I have multiple elements in my recyclerview's row -> By multiple I mean multiple in number as well as multiple in type i.e mutliple imageviews, textviews etc.
Following is the gist so that you can see all the elements: https://gist.github.com/Harshhb101/55e25da72e3a474aeeb422d5e231d3e3
The issue is that I need to hide/show these elements based on a parameter which can have upto 10 values. Thus I will have 10 types of rows. Currently I have created only one layout for the row have elements for all types of rows and in some mobiles, the scroll has a lag. Majorly I am getting the lag where the rows have images. I am using Glide to load the images. Following is the gist for the onBindView: https://gist.github.com/Harshhb101/e10feb2cccda9d698ff06487bbb879ef
I did look up on stackoverflow but could not find anything solid but came upon using multiple viewholders. My question is that if I refactor my code, will it make a substantial difference by using multiple viewholders? Or is there something wrong in my approach that could be fixed to get a good scoll.
You need to make your RecyclerView images smaller to save memory and cache them. Read this.
Also if your ViewHolder contains images that has size wrap_content then images are loaded full size what is really bad for performance for example if view size on screen is 48dp x 48dp and picture is full HD, then full HD drawable going to be loaded in to memory what is making your scrolling slow and not smooth.
I suggest using fixed size in ViewHolder or override image size when loading in Glide
Please declare many view type instead of one view type for many kind. It's actually make the code more readability, but not much the reduce the lag because the recycle view/listview is have the reused mechanism.
Recommended to use fixed size in RecycleView.
I saw the Glide used for image loading. So did you config the cache?
I have doubt that you loading the big resolution image
After looking into the code i found couple of improvements.
Don't make God ViewType (One view type for all kind of views). instead create
individual viewtype for each kind of posts. so it'll eliminate the rendering cost of all the views and making them visible and invisble at runtime.
Reference demo of recyclerview with multiple viewtypes
Use some image loading libraries so that you dont have to handle caching images and bitmap related manipulations (Picasso will be good).
Picasso
And lastly avoid doing heavy tasks in onbind() instead prepare your data class specifically for recyclerview (if much caluclation required like heavy string manipulations etc) before setting recyclerview adapter.
Got some good feedback. Originally wanted infinite scroll. Removed it. I am also an interested in a solution with pagination or that just handles a simple case of the first 20 results to start. The main thing I want to know is the best types of views to use. Question was very vague at first. Narrowed the scope of it, too.
I want a view that fills the phone or tablet's screen with tiled images from an api.
How I'm thinking about doing this:
putting a GridView in my layout
using the Picasso library by Square to load the images (possibly do more, not sure what it can do for me)
making an adapter to the GridView
doing a query to my api (in this case getting popular movies)
processing the query results and turning them into an ArrayList of Strings or Uris with the image locations (for popular movie posters)
passing the list to the adapter to the GridView so it can show the images.
I don't I know enough about Android to think this through fully yet. I'm in the process of learning.
Any suggestions for better design, tutorials on similar things, or things that may make this easier/better?
Thanks!
I'm using Android-Universal-Image-Loader in a ListView of mine and I'm trying to find the best solution to following:
using resetViewBeforeLoading is necessary or else I get the same image in my ConvertViews, but this causes jitter, unless..
I use PauseOnScrollListener which is otherwise great, except that it shows a blank in some ConvertViews even for images that are already downloaded (I'm using memory and disk caches), so it's confusing to the user who sees a blank for an image they saw only 2 swipes ago
So it seems that I can't get an instant image load (for already-downloaded images) on scroll without jitter, even for images in memory, is this about right? Is there a better or more standard way to do this? (Vertical list-view showing screen-width images, sort of like the Instagram app, which does it buttery-smooth)
Otherwise, is there a way to lengthen the number of convertViews in my ListView to prevent unnecessarily aggressive re-use?
Thanks in advance
I've a ListView in which each row item contains many ImageViews apart from some content.
That is, there will be many list items, each containing many images.
In order to not to hold user unnecessarily, I'm showing the content first & then downloading the images asynchronously.
Currently, for each image I'm starting a new AsycTask.
Although, it working alright, but this not a good approach.
In place of this, what should I use?
use this library, best in android for image loading..
https://github.com/nostra13/Android-Universal-Image-Loader
Your scenario seems to fit exactly to use LazyLoading of images. This basically loads images in the background and shows them as soon as they're loaded.
You might want to see this:
Lazy load of images in ListView
An alternative would be using a ThreadPoolExecutor with the images to load, but the above works pretty well and is recommended.
Try using the library
http://square.github.io/picasso/
Many common pitfalls of image loading on Android are handled automatically by Picasso:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
I'm developing an Android app with a list view that contains lots of drawables.
Most of them are the same so I'm trying to use a HashMap that returns the same allocated bitmap when it's needed but still there are lots of allocations and GC actions so that the list gets stuck from time to time when scrolling.
What can I do to optimize the performance in such case?
Caching method - loadImage Using google code
mImageWorker.loadImage(pic_url, holder.pic);
holder.*some bitmap*.setImageBitmap(Utility.getBitmap(context, id); //can be one of 5 bitmaps do I use caching with a hashMap
see this example
this will helps you....
don't put so much process under the getView() method . this will lack the listview scroll performance
if you want to do image crapping or drawable to bitmap conversition or anything .. just do all process
before loading adapter.. and just assign values for each row in getView()...
Try to use lazy loading technique using caching, you can find many tutorial on the web:
You have to see this SO thread
Also see this:
Multithreading For Performance, a tutorial by Gilles Debunne.
This is from the Android Developers Blog. The suggested code uses:
AsyncTasks.
A hard, limited size, FIFO cache.
A soft, easily garbage collected cache.
A placeholder Drawable while you download.
If you want to optimize the code, try lazy loading concept for loading images in list. Please refer: Lazy Load images on Listview in android(Beginner Level)?