Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

What is the android UI thread stack size limit and how to overcome it?

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:

  1. 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?

  2. 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?

  3. 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.

  4. Assuming there's no miracle solution on #3, any recommendations for where the core hierarchy optimization should be done?

  5. 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()?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...