I have a problem with a BI application I'm writing.
The application uses AChartEngine for charts and most of the table data is inflated programmatically. There are currently two main problems I'm facing:
When the application switches orientation, it takes around 8-10 seconds to redraw every dashboard element (i.e. to display data). Is this a problem with overdraw or something else (this happens on N4, N5, Note 3...). This is unacceptable and I really need to fix this!
There's almost 4x overdraw on table row elements, and I managed to get it lower - to around 2-2.5x with getWindow().setBackgroundDrawable(null). How do I fix this much overdraw as everything is inflated from code? (here's an example of how it looks like: http://prntscr.com/2lio5q).
Regarding overdraw:
Have you checked Romain Guy's Android Performance Case Study:
http://www.curious-creature.org/docs/android-performance-case-study-1.html
You can also find several Google I_O Videos by him (some of them dated) that might be helpful.
I finally fixed the orientation working very slowly. I applied few flags to my FragmentActivity in the manifset and it works much better now, flags are android:configChanges="screenSize|orientation|keyboardHidden".
Keep in mind that for this kind of thing it is much better and Android-like to use the FragmentPagerAdapter than FragmentActivity, but I work with what I got.
Hope this helps someone!
Related
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.
I have two ImageViews which I hope imageViewA is overlapped by imageViewB, and when user select a seekbar, the alpha value of imageViewB will change accordingly (e.g., becoming translucent and users can see part of imageViewA).
It supposes to be a easy coding task, however I found the performance is VERY slow in my Galaxy S6.
I have tried all setAlpha(int), setAlpha(float), and setImageAlpha(float), but get no hope. It seems the most related question post is App UI operations (setting alpha, setting margins, etc.) very slow on 4.4.4 compared to 4.0.3
However, this question is still open. Does anyone knows how to speed it up?
---- Here is some updates ----
The minimal code is just simple, in the seekbar callback I made
imageViewB.setAlpha(selectedAlphaValue);
The VERY slow means the fps is less than 1~2. I do hope I can get the alpha changed 10 times a second to make users feel comfortable. (BTW, I don't benchmark the delay of set alpha function because it is TOO SLOW, even my human eyes can notice it only changes 1~2 times per second)
Thanks Nikola,
ViewCompat.setLayerType(view, LAYER_TYPE_HARDWARE, null)
Is the right thing to do. It solve my problem like a charm.
Could you please post your reply as an answer, Nikola? So I can rate you as the correct answer.
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 ran a Traceview on my Android app and the result was terrible: 2200msec. I've talked with a lot of people and have been told to go up or down the stack and find the offending code. The problem is, when I go all the way up, or all the way down the stack, there's no obvious indicator as to why (I know you're scoffing, because you're right, there is a reason, but please read-on I'm new).
If I look at Excl CPU time, BitmapFactory.nativeAssetDecode is taking a huge amount of time, well over 1400msec. Obviously this is a major part of the problem with my Activity, however, identifying where this is coming from has been a nightmare. None of my "direct" code is anywhere near (not a Child, nor Parent) this part of the stack, in fact, all my "direct" methods appear to be well-behaved, firing and finishing in mere 0-4 msec as would be expected.
One thing I've found is if I start my Traceview AFTER setContentView(), the Traceview log drops to just 90 msec. I'm honestly too new to understand this result, I know this is misleading because of course setContentView() takes time, but perhaps my layout is causing WAY too much time to be taken? Could my layout really be causing 2110 msec?
This is where I'm confused. My layout has zero overdraw and appears to be a well-formed and non-redundant XML file. My biggest layout has 41 view widgets in it, I swear I've seen many well-performing Activities with over a 100 view widgets in them. My view is designed of essentially 4 Layouts and 36 view widgets (TextViews, etc), each of these items has a Style assigned to them from the Style.xml. I hope I haven't taken things for advantage and created a monster view?
Perhaps if someone could expand on the theory to trace issues when they aren't caused by direct code you write, or the theory behind isolating the cause of the CPU time for "runaway" methods, I'd be able to better help myself (and God knows I've tried, this entire weekend in fact).
TL;DR If I start my Traceview AFTER onCreate's setContentView() it takes 2110 msec less time to load my activity than if I put it BEFORE setContentView(). My Activity's view isn't exactly complicated though, so I'm confused.
I appreciate it so much,
Ryan
One of the things that can really hurt you is to have layouts whose measuring affect each other. I would be that you are using lots of "weights" in your layout, as these are a bit time intensive to calculate.
You can analyze your slow layout using hierarchyviewer. This is in the Android tools menu in IntelliJ or in Eclipse. It only runs on test devices, or with apps that have added ViewServer (see this for instructions)
One note-- green, yellow, and red are relative to your current view Hierarchy. Here is a note from the documentation:
These indicators can be red, yellow, or green and represent how each
view renders in relation to other views in the tree. They are not a
strict representation of a bad or good view, per se.
A red dot means that this view renders the slowest, compared to all views in your hierarchy.
A yellow dot means that this view renders in the bottom 50% of all views in your hierarchy.
A green dot means that this view renders in the top 50% of all views in your hierarchy.
It really is just an indication of what you should try to fix.
Well, I found the problem and it's bitter sweet. It's sweet because it wasn't my code nor layout causing the problem, it was the admob AdView using the loadAdOnCreate="true" to create ads. It's bitter, because I now may have to switch sources of revenue if I can't remove the loading delay created by the AdView!
Hey all,
I am having an unusual problem with my Game. I am loading six textures in my Game, the initial one is a type of Game Background. Now at click of a Sprite i load a Dialog with infalted XML. The problem occurs here, when it first loads my game Background becomes black, when it reloads again it returns to it's original, when it reloads again it's black and it continues like this. It's a big code and that's why i cannot post it here, may be any one of you help me in this. I am stuck since many days in this, I have not unloaded any Texture, but still it's looking like that...............
Hope to get some help from you all..................
Thanks............
Try copying your game to another project and keep removing stuff to narrow down the problem until you don't have the problem anymore. I'd start with removing textures.
How many textures of what size do you have?
This is my raw guess.
you could have kept the Dialog's inflated xml root layer's(linearlayout) height and width as fill_parent. This could have occupied the entire screen and let things black.
make it as wrap_content to both.
1024x600 Textures are impossible! Both dimensions have to be a power of two, AndEngine does not accept other dimensions as many (all?) devices would not allow this.
Sorry but my time is currently very limited (due to exams =( ).
kkkkk SO it's a very delayed answer but still, may be it may help others. I exactly don't know what the problem was but after removing a texture, making size of some other's small, and also when android got updated, the problem is now very delayed, or it rarely comes.
So as per what i can think there seems only two issues, some memory prob or some bug in android which resolved with new update.