I am freelancing to solve crash of an android app. It happens on startup, and I know it is because the activity_main.xml. It has too many views, too many nesting levels. Apart from that (wich I will try to reduce)
what are other strategies to improve layout performance in Android?
The user interface cannot be changed or simplified.
For example:
- for repeated elements (50 - 100), does using 'include' makes it faster?
- the same for defining properties in styles instead of in every item.
I have been recently working on improving performance of app and renderd a fast smooth UI let me share you my experience :
The vision of performance in terms of UI is:
Lower the latency of screen draws
Create fast, consistent frame rates to avoid jank/lag.
And there are some thumb rules for layouts .
Minimum view hierarchy.
minimum background drawbles
minimizing overdraw of window :
minimizing overdraw of Views
using drawble left instead of image and textview aligned horizontally.
using lists/recyclerview very often when repetitive view
and Many more . let me share some links which are really helpful
https://medium.com/#elifbon/android-application-performance-step-1-rendering-ba820653ad3#.pp7hpnv07
https://www.safaribooksonline.com/library/view/high-performance-android/9781491913994/ch04.html
https://riggaroo.co.za/optimizing-layouts-in-android-reducing-overdraw/
https://www.hackerearth.com/notes/rendering-performance-in-android-overdraw/
Letme know if it's helpful. Cheers
You can try following from https://developer.android.com,
Optimizing Layout
Inspect Your Layout
Revise Your Layout
Use Lint
AS well as
Improving Layout Performance
Optimizing Layout Hierarchies
Re-using Layouts with
Loading Views On Demand
Re-using Layouts with
I have answered a related question before and my advice is still applicable in this topic.
Handling loads:
Lazy Loading - Load only those piece of information that is really needed by now. Example : A Movie app: Load only those latest movies rather than those old movies unless the user told you to do so. The idea here is that decided only on which is necessary to load first and load other else later on. The lesser the load the greater the performance is while without sacrificing a good content.
Caching - If you keep on downloading things from your server chances are it might take too long to load and your splash screen will be visible for longer period of time or some of your UI might freeze specially when you do it in the Main thread. With caching you will need to fetch fewer data from the network since you've downloaded some of them already.
Things to consider in creating views.
Avoid a super deep nested views.
Avoid a deep nested weights.
For image loading use some popular library like Picasso, Glide etc.
does using 'include' makes it faster?
A bit, Reusing layouts is particularly powerful as it allows you create reusable complex layouts. For example, a yes/no button panel, or custom progress bar with description text. It also means that any elements of your application that are common across multiple layouts can be extracted, managed separately, then included in each layout. So while you can create individual UI components by writing a custom View, you can do it even more easily by re-using a layout file.
Source : Official docs
Addendum
When things are still wrong and the Android framework doesn't provide what you really need; the last approach is to create your own view via extending View or ViewGroup. Creating your own view/layout requires time and much effort but you gain more controls since it is your own view/layout implementation, let say you have the power to change the world.
Related
I had been using nested views in one of the screens in my android app. Now that I have removed all of them and used a ConstraintLayout for performance gains, I want to measure how much the performance has increased. Is there a way to measure the performance gain?
The easiest way is probably just to profile the app using a profiler using the old code and the new and see how much inclusive time is spent in onLayout in both versions.
Expect the difference to be less dramatic than you expect. The reality is your main thread is going to be idle most of the time, improving layout efficiency is really rarely a big factor in your app's performance. I would never refactor a nested design for that, I'd refactor a nested design if using constraint layout gave me cleaner XML for my view. Also remember that depending on what features you use, constraint view may not be faster. Its quicker to layout a nested linear layout than it is to calculate a whole bunch of constraints on multiple inner views, for example.
I am building an application using Android Studio for an android tablet. I am fairly new, have never published an application. I have several parts I use on more then one page so I implemented them as fragments. On the page I am working on uses 4 fragments and when it renders, I get the message, Skipped 36 frames. If I change the fragment body from the page xml file to a constraints layout the messages go away. I've cut each of the fragments down to bare bones to get then number of skipped frames down to 36. If I put the components back in, the skipped frames go to 96.
Is there an alternative to fragments to share code within android?
I have run systrace for the loading of the page and the measure took 1441.6ms while the layout took 8.31ms.
There are other problems of course, but sorting out how to get this down to something reasonable would be good.
Also, Could this just be that the tablet is slow? Is there a place to see benchmarks on specific devices? Then I could maybe just use a different device.
Edit
If I flatten the xml, replace the fragment and put the xml for the fragment inline using a surrounding <ConstraintLayout it is slightly worse?
Edit II
I have worked on this issue all morning. I went back to the fragment implementation, then I went through the process of removing some ConstraintLayout sections. I used ConstraintLayout to delineate areas on the display. So I figured I could increase performance if I could remove some of them. Well, not so fast, sometimes when I removed the ConstraintLayout it actually made the application skip more frames.
Then I did an experiment on where I used margins and borders. It turns out if you use margins on a ConstraintLayout is faster, depending on the content of the Constraintlayout, then adding padding to each of the elements.
Also, a bigger cost is asking the ConstraintLayout to fill all available space using height/width="0dp" All of these attributes are part of the measure phase so they impact the frames skipped.
My consensus is that the tablet doesn't have enough power to write an application that makes any good use of the screen. Think of the tablet as the screen real estate of 4 phones. If the cpu is not way bigger it will not be able to manage that size of a display, unless all you want to do is draw images on it.
I have an XML file with about 150 views. Yes, I know it is a lot and I did get a message from Android Studio saying I can't exceed 80 views. But I can't drop views any lower than 150. I considered using list view but it works the way I wanted it to.
The question is, will this many views make the app crash/slow the device? I've tried it on my s7 and it works perfectly fine. My lowest API is 17 which is 4.2. Wouldn't 4.2 devices be able to handle this XML without any problem?
Thanks.
The problem with having an excessively large number of Views is that Android often needs to measure, layout, and draw them, and it will traverse the entire View hierarchy to do this. If the number of Views is so large that this traversal takes more time than the screen refresh rate, you will skip frames and your UI might appear to lag or be choppy.
If not all of those Views need to be on screen at once (for example, if you are using a ScrollView to hold a very large container that the user can scroll through), then you should probably switch to using RecyclerView.
If all of those views need to be on screen at once, then you might consider writing custom Views that can display your content all at once instead of having individual Views that draw individual things. This can drastically reduce the time and complexity of the measure/layout/draw traversals.
It's difficult to suggest an approach without knowing more specifics about your UI, but hopefully that explains the issue.
I'm getting java.lang.StackOverflowErrors when my view hierarchy is being drawn:
at android.view.View.draw(View.java:6880)
at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
at android.view.View.draw(View.java:6883)
at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
...
Research points to my view hierarchy being too deep for Android to handle. Indeed, using Hierarchy Viewer, I can see that my longest nesting is 19 views (!)
My app looks somewhat like the Google Play store app (with swipe tabs). Every tab is a nested fragment inside a fragment view pager - using v4 support and HoloEverywhere. Obviously, this is why my hierarchy has gotten a bit crazy.
My questions:
What is the real stack size limit? I found no way to measure the stack size of the UI thread. Some rumors on the net say 8KB, but is there a way to measure this accurately on some sample devices?
Does the stack size limit change with OS ver? The same hierarchy does not crash on an 4.0.3 device but does crash on a 2.3.3 device (identical hardware). Why is that?
Is there any solution except optimizing the hierarchy manually? I found no way to increase the ridiculously small stack of the UI thread. Sorry, but 60-100 stack frame limit is a joke.
Assuming there's no miracle solution on #3, any recommendations for where the core hierarchy optimization should be done?
Crazy idea - I noticed that every view layer adds about 3 function calls (View.draw, ViewGroup.dispatchDraw, ViewGroup.drawChild). Maybe I can make my own ViewGroup implementation (custom layouts) that is less wasteful on stack during draw()?
I believe that the main thread's stack is controlled by the JVM - in Android's case - Dalvik JVM. The relevant constant if I'm not mistaken is found in dalvik/vm/Thread.h under #define kDefaultStackSize
Browsing for stack sizes through the dalvik source history:
API 3 (Android 1.5) = 8KB
API 4-10 (Android 1.6 - Android 2.3.7) = 12KB
API 14-17 (Android 4.0 - Android 4.2.2) = 16KB
So how many nested views can you have:
Impossible to say accurately. Assuming the stack sizes are as described above, it all depends on how many function calls you have in your deepest nesting (and how many variables each function takes, etc). It seems that the problematic area is when the views are being drawn, starting with android.view.ViewRoot.draw(). Each view calls the draw of its children and it goes as deep as your deepest nesting.
I would perform empirical tests at least on the devices appearing in all the boundary groups above. It seems that using the emulator gives accurate results (although I've only compared the native x86 emulator to a real device).
Keep in mind that optimizations to how the actual widgets / layouts are implemented may also influence this. Having said that, I believe that most of the stack space is eaten by every layout hierarchy adding about 3 nested function calls: draw() -> dispatchDraw() -> drawChild() and this design hasn't changed much from 2.3 - 4.2.
I would give this and this a shot, it will solve many of your questions and help you to further understand why a bigger stack is not really needed in the uithread. Hope it helps!
I don't know what the stack size limit is, and quite frankly I don't think searching that out is going to be of much use. As your second suggestion suggests, it could very possibly depend on what version of Android and/or the Dalvik VM is present on the device.
As for optimizing your layouts, some options include:
Use RelativeLayout instead of nesting ViewGroups, particularly LinearLayouts inside LinearLayouts, to help flatten your view hierarchy. This is not an all-purpose solution; in fact, nesting RelativeLayouts can hinder performance (because RelativeLayout always measure()s twice, so nesting them has an exponential effect on the measure phase).
Use custom Views/ViewGroups, as per your fifth question. I've heard of several apps that do this, and I think even some of the Google apps do this.
If you find any useless children in your view Hierarchy, you can try using the <merge> tag in some of your layouts (I myself haven't found many uses for them however)
Crazy idea 5 - May be not so crazy. I explain you the theory and you try implementing it some how. Lets say we have 3 nested views A > B > C. Instead of C be nested in B make it nested in D(some unrelated view) and when B will go to draw him self he need to call B.draw(). Of-course the problems you may run in to is bad layout. But it's possible to find solutions for that.
A better explanation of my crazy idea 5. I'm not saying it's a good idea :) but I wanted to clarify how it can be done.
We will create our own implementations for the basic layouts (LinearLayout, FrameLayout, RelativeLayout) and use them instead of the originals.
The new layouts will extend the original ones but override the draw() function.
The original draw function calls dispatchDraw() which calls drawChild() - and only then you get to the draw() of your child. This means the draw() in each nesting adds 3 function calls. We will try to minimize it into 1 function call manually.
This is the disgusting part. Are you familiar with inline functions? We theoretically try and make the calls to dispatchDraw() and drawChild() inline. Since java doesn't really support inline, the best way would be to manually make them inline (actually copy-paste the code inside into a single disgusting function).
Where does this get a bit complicated? The implementation we would take would come from Android sources. The problem is that these sources may have changed slightly between Android versions. So one would have to map these changes and make a set of switches in the code in order to behave exactly like in the original.
Seems too much work and it's one hell of a hack..
I am an experienced developer, but I'm inexperienced on the Android platform. So I am seeking some advice from developers with more experience with Android.
I am building a Honeycomb application using Fragments. One of the fragments calls for a vertically scroll-able read-only "HTML table-like" view with dynamically loaded data. Similar to a spreadsheet, I should have clickable headers which I can implement server-side requests to filter/sort the data.
I am pretty sure this Control doesn't exist yet, am I right? Do I have to build it?
Assuming I have to build it, which existing widget should I extend? ListView, Table, GridView?
I assume I would have one widget for the header, and then wrap the body of the table in a scrollable layout to handle scrolling while keeping the header visible. I am concerned that I might not be able to guarantee that the headers line up with the columns.
Thanks in advance,
Tim
Android layouts are pretty basic - there are not any shipped layouts that will really do what you are looking for automatically, but you could probably do what you want with a heavily controlled gridView. Android is also pretty bad about controlling multiple elements to fit within the screen size, as it's goal is to support multiple screen sizes and densities.
From what I understand your desire to be, I think the best solution is to create a nx2 grid view dynamically, and control the width of the view based on the device size. You would have n number of headers on the top, and you could fill the lower half of the grid with your textViews, or whatever data you wanted. The hard part would be keeping the widths of the grid elements under control and on the screen. In addition, you will probably find that you can only fit a small number of header items on the screen because of the phone's small size, so you may discover a better layout to fit your needs.