I have a ListView with each item being a custom layout with multiple Views (including a large image of ~445x250, a smaller image of ~40x40, etc). While scrolling, the animation is extremely choppy.
Can someone recommend how I can improve performance?
One approach I tried was to eliminate any transparency in the images being used. This did improve it slightly, though there is still a noticeable lag when before a new item scrolls into view.
Update:
Here's the View heirarchy for the custom layout (for each item) - http://pastie.org/3333903
Looking at the layout provided, there are a few things that may cause performance issues:
Your View Hierarchy has a depth of 4. You should make your View Hierarchy as shallow as possible. Consider using a RelativeLayout/TableLayout where possible instead of nested LinearLayouts.
You have nested weights. Try to avoid having nested weighted views.
You have a lot of views for a row item. Remember the purpose of a ListView - if your rows start becoming complex, it may be a sign to look at something else to display this information.
A GestureOverlayView seems a bit heavy for a ListView row item. Is this necessary? Considering ListViews a scrollable by touch, having custom gestures on row items may be a bit confusing.
You can also try using android:persistentDrawingCache="scrolling" and the ViewHolder pattern to squeeze out a bit more performance.
If you download the latest version of ADT, it will also guide you in optimising your layouts.
Apart from layout optimisations, minimal work should be done in the getView method of your ListAdapter.
Additionally, you can use android:hardwareAccelerated="true" to take advantage of hardware in Android 3.0+.
You can use the dynamic table layout instead using the List view. It will improve the performance. Dynamic table layout will adjust the large image and smaller image. It will be of help to you.
Related
I want to use CardViews in my app only for the visual effect.
All CardViews will contain very different views, so I cannot really design a good adapter and thus I cannot use a RecyclerView.
The result is perfectly clean, but for this I had to nest a lot of ConstraintLayout, and so the layout take several seconds to draw itself. (any advice on how to measure more precisely this delay ?)
Here the hierarchy of my layout (with 9 CardViews and not 2):
ConstraintLayout
-Image + text x4
-ScrollView
--ConstraintLayout
---Cardview
----ConstraintLayout
-----text, spinner, button, etc
---Cardview
----ConstraintLayout
-----text, spinner, button, etc
You can see the max depth is ConstraintLayout>ScrollView>ConstraintLayout>CardView>ConstraintLayout, which seems inefficient as hell, as stated in the Android Optimizing Layout Hierarchies Guide.
What should I do to flatten my layout ?
I think your setup is fine. And not too deep. The layout is probably not the problem.
Note that it only draws the item on the screen. It does create layouts for the others in the ScrollView, but does not render them. If the drawing was the problem, the scrolling would be slow. You can check that.
Layout might be slow, but I doubt it. There are ways to monitor this though.
Are you loading all images off the UI thread? Nothing on the screen is coming from a server or going through some other complicated (parsing) method?
SOLUTION 1:
It's okay for RecyclerView to load different views and you can design good adapter for it. Check A RecyclerView with multiple item types and Heterogenous Layouts inside RecyclerView.
SOLUTION 2:
Considering your hierarchy you can place your cards directly to ScrollView without ConstraintLayout:
ConstraintLayout
-Image + text x4
-ScrollView
--Cardview
---ConstraintLayout
----text, spinner, button, etc
--Cardview
---ConstraintLayout
----text, spinner, button, etc
Here is an easy solution: Don't use nested ConstraintLayouts, the idea of ConstraintLayout is to reduce the amount of nested objects, but there is a performance price for it.
Base on this comment it's up to 3 times slawer than RelativeLayout. And I think that nesting it only increase the problem.
So try replacing ConstraintLayout with RelativeLayout and please reply here with the difference in performance, I bet you will see one.
My question is about best practices in Android in terms of using ScrollView to scroll other views and widgets. This is to know when to use a ScrollView to eliminate redundancy of scrolling if scrolling is possible in a given widget/view/layouts.
So I notice that there are instances where I don't really need to use ScrollView to make things scrollable. Few of the widgets/views/layouts that I know of are TextView and ListView. This is supported according to this documentation.
You should never use a ScrollView with a ListView, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.
The TextView class also takes care of its own scrolling, so does not require a ScrollView, but using the two together is possible to achieve the effect of a text view within a larger container.
My question is, are there other widgets/views/layouts that handles their own scrolling other than the two I have stated above and the documentation has. Maybe there are others that are scrollable or other methods to make things scrollable other than the default of some widgets and by using the ScrollView.
Preferred answers must be base on experience and documentation (other than what I've shown). Thanks in advance for any good answers.
WebView is one other class that does its own scrolling. My "best practice" advice is to use ScrollView to add scrolling to an arrangement (usually vertical) of fixed-size widgets. As you have noted, variable-sized widgets such as ListView provide their own scrolling.
if you read the official documentation you will find that tell you when not to use ScrollView:
You should never use a ScrollView with a ListView, ListView Because Takes Care of Its Own Vertical scrolling. Most importantly, doing all of the defeats esta Important optimizations in ListView for dealing with large lists, since it forces the ListView Effectively to displays its Entire list of items to fill up the container supplied by ScrollView infinite.
More information here.
I have this situation I wanted to discuss:
I have a listview that it's purpose is show 25 stores.
For the design I want I have:
2 layouts, the first one has:
1 big photo of the store (downloaded from a database).
1 icon if the store belongs to the best rated stores list (that icon is on my app)
1 textview (downloaded string)
the second has:
3 textviews.(downloaded string)
Everytextview has a custom typeface.
As you can Imagine, this is a huge task for each item.
My main question is:
Wouldn't I get a much better performance if I downloaded everything and instead of making a listview I populate a scrollview with this data?
It might take a bit more to create the layout but probably it would be smoother scroll or am I wrong?
You can do the same with ListView (download everything and display), but I don't think that "downloading everything" will actually bring any performance improvements (except you're talking about cache).
ScrollView will lead to much worse memory performance as you'll have to create and keep 25 views at once. On contrary, ListView reuse the same views while scrolling which will result in creating approximately as much views as it can fit on the screen.
With ScrollView, if dataset changes, you have to somehow repopulate your 25 views. In worst case recreating all views.
Moreover, going with ScrollView you'll have to deal with 25 big photos in memory at once which will probably give you nightmares for a few days.
From my experience, if the number of elements in the list is less than 50 and the layout is not using too much memory, then you might be better off using a scrollview.
ListView is designed for much bigger dataset, and it's designed to reduce memory usage rather than performance. There are tons of work that Google put into it to optimize its performance. Together with viewholder pattern and modern hardware, and the perceived performance is close to fully populated scrollview.
But again, why need Listview if the dataset is small enough that doesn't affect memory usage? ListView is tricky to use when combined with fancy animation due to the underlying funky optimization done by Google.
What I have learned from a similar problem is that the scrollview is smoother that the listview. My case was to opt one for the navigation drawer, because smooth inflation and scrolling in the drawer has direct impact on user experience.
I first adopted the listview but it was by no means smooth. Then I found that found here that google developers use scrolview instead of listview for the drawer that works smooth for me either.
But if lazy loading of the list items is what you require(not in my case), then you should go for listview.
Currently, I am having a ListView with different list item view for each row (Most cases Different).
I am having 6 different item layout, I will add more in future, and I will have only like 5-15 list items, some time may be less and may be many in other cases.
Some item views contains:
ViewPager
ListViews
ImageViews
Texviews
Gridviews
CAROUSEL
Webviews
As this is dynamically generated depends on data, I am facing following issues :
Scrolling Slowly (Some Times)
List Item height
Performance
Is RecyclerView the best solution in this case?
Without seeing your code to identify specific concerns, it's hard to address specific reasons why you are seeing such performance problems. Such as, are you properly using the ViewHolder paradigm? Or are you inappropriately loading stuff on the UI thread when it should be loaded on a background thread? Android has a small section talking about scrolling smoothly with a ListView you should check out. That aside,based on what you have mentioned so far...I think you major problem is design.
Problems
If your ViewPager is using a FragmentPagerAdapter...then that will definitely be causing a lot of overhead and performance drag.
ListView: You should never ever place a ListView within another ListView. This will cause all sorts of problems. Android does not like embedding two scrollable widgets that scroll the same direction. Even if this worked, it'll cause some major performance problems.
GridView: Same goes with the GridView. You should never ever place a GridView within another ListView. Even if this worked, it'll cause some major performance problems.
If you're ImageView is loading some large graphics, it should be on a background thread and not the UI thread. Else you'll get some slow performance
Carousel - I have no idea what API this is but if it scrolls vertically, then it's a no go.
WebViews are a very heavy weight object. I can definitely see this guy slowing things down, especially if it's loading a lot of content.
To build off what #Joffrey has said. There are some major concerns in your choice of UI. Based on what you are placing in this ListView tells me that you need to seriously rethink how to display your content to the user. Eg, try using a TableLayout or GridLayout instead of a GridView.
I need to display a complicated list in my app. On each row there will be a checkbox and some TextView.
I know this could be done via ListView/Adapter, but I was worried it requires too much tweaking to make it fits my specific requirement, so I just created my own customized MyListView inheriting LinearLayout. On initiating, it adds MyListViewItem (inherited from RelativeLayout) dynamically.
The customized view functions fine. However, I notice that the rendering speed of MyListView is a little too slow, so I wondered will it be faster if I use ListView/Adapter instead?
Thanks,
The benefit of using ListView rather than a great big LinearLayout is that the OS can do a better job of optimizing when views are inflated, and the recycling of views, based on what is actually visible to the user. It also makes it easier to perform common actions such as scrolling to a particular row.
ListView recycles its items. So, yes, it will work much more efficiently in case of a large number of list items. And as a result you'll obtain a less complicated view hierarchy.