We have an data-driven activity which constructs a large set (typically, up to 100) of Button-like components and places them in a Scrollable. Each of the buttons is inflated from a resource and are based on a RelativeLayout. The button has two text views, two image views - both from resources - and has a background of a 9-patch.
The size, position, text, and configuration of the image views are all driven from a database query.
Unfortunately, this is taking between 2-3 seconds to layout on an HTC Desire, 3-5 seconds on an HTC San Francisco or HTC Sapphire.
Once the initial layout is done, the view performs beautifully.
We have tried a number of strategies which made no difference:
time the database query - this was not a significant part of the delay.
cache the buttons, to reduce the amount of layout inflation.
constructing a subtree of views outside of the “live” view hierarchy, then connecting it when complete.
doing the same on another thread, but connecting the subtree to the activity on the UI thread.
We have an indefinite progress indicator (spinner/throbber) which spins while the query runs on another thread, but then freezes when layout gets going.
So, my question are these:
how can I make the layout of the views seem more responsive or
how can I avoid the thobber locking up while layout occurs
Thanks.
Edit
The scroller is set to scroll horizontally and vertically. So we have a grid which the screen is a viewport on.
This makes using the built in ListView (at first glance) unsuitable for the task.
The progress indicator will not redraw during layout, because it's all happening in the UI thread.
To improve performance you should use a ListView, it's scrollable and the items can be customized (you can reuse your RelativeLayout based "button") with a custom adapter, and it allows to recycle the items while scrolling. See Recycling views in a listview, worth it?, and above all this excerpt from CommonsWare's book on Android.
Related
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 am creating layouts at run time using heavy data, and adding these layouts to a scroll view. After the view get created, its working fine. The problem here is, the data is very heavy and it takes more than a minute to create the screen, which is not so good user experience. I want to create layouts only for the part of screen that are visible, and rest I can create on scrolling the scroll view. Pls suggest how is that possible? Also, If someone has a better approach, Pls suggest.
You can start by creating only a set number of views each time[1], but always add a dummy 'loading' view at the end of the list if there are more views 'pending'. As soon as the user scrolls the ScrollView at the end of the list, start loading the next part of views on a background thread, and as soon as they are built, remove the dummy loading view, and add the new views into your container.
An other approach would be to start loading the next group of views, as soon as the previous group is done finish, but that might be a waste of resources.
An even better approach, is to combine those two methods described, and always have the next group of views being created, if the user is halfway done scrolling to the end
You can check how to know when the scrollview scrolls to the bottom here: Android: Detecting When ScrollView Hits Bottom
[1] Since you care about UX I would suggest that the number of rows should depending on the row's height and device max height. I.e. 4 views on a small device, 6 on a medium, 10 on a large.
I am not doing any network operation like downloading images or media in my Ui thread. i have a very complex UI that takes around 8 seconds to load and black screen comes in between , is there any way i can optimize it or show some kind of progress bar while my second activity loads its UI and remove the progress when i am done.
I cannot use asynctask doInBackground() since everything is UI only --Like For loops for creating LinearLayout childs dynamically, Putting views side by side on relativelayout and reordering them as per business rule. changing various image colors as per business rule etc.
Is there any way i can optimize this and reduce loading time?
Why you need such a complex layout in the first place? if the layout is too complex then it should NOT be. Try to find a simpler layout, if you must follow the current layout then I suggest an idea but it is not recommended.
Here is the idea, it's based on iOS development, you should take a snapshot of the complete layout (without any actual content, just layout) and display on top of your layout when you first load your activity. After all of your underneath layout already loaded, then you remove the snapshot on top and make the real layout visible (all the process must show the loading progress to avoid user interact with your UI). Although this is not ideal, it should help in your case.
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.
I'm researching creating a view for displaying EPG data. That is the view should:
have a fixed header column that shows the services,
have a fixed header row that shows the time and
a content area that has equal-height TextViews of flexible width for showing the actual EPG entries
Most importantly, scolling vertically must scroll header column as well, scrolling horizontally must scroll header row.
Apart from drawing the whole view myself (inside a scrollable?) I'm totally stumped if there is any good approach I could use involving linear layouts or such.
Any hints are greatly appreciated- please note that I'm and android beginner.
Approach 1: Everything (that is all views) are pre-generated.
Have top and left one-way ScrollViews together with a bidirectional ScrollView and have the scolling be synchronized ( Android: Synchronized scrolling of two different views ). Synchronized scrolling isn't to difficult to do if you've subclassing the ScrollViews and add your own ScrollManager to handle notifications.
Drawback: ScrollViews inside ScrollViews for the main content area do seem to be the desired option. The whole thing will become highly resource intensive as all items need to be created upfront to be available for scrolling.
Approach 1 takes care of view-synchronization for the scrolling, but is a huge resource hog (imagine an EPG with 30+ channels and 100+ events per channel).
Approach 2
One approach for this I could imagine would be- for the main content area- a ListView with a custom ArrayAdapter. Custom adapter would probably return a LinearLayout or similar holding the individual events. That way, scrolling would still work bidirectionally if the ListView is put into horizontal ScrollView and at least the LinearLayouts themselves could be recycled by the ListView.
Are there better approaches?