I'm struggling with StackOverflowErrors in the main UI thread (related question). My app targets Android 2.3+. On Android 4 everything is fine, but I'm getting crashes on 2.3.3 when the view layout is drawn.

The obvious answer is to optimize my view layout and reduce the number of nested views. This is a problem because the large number of views is due to me using the support library and fragments for tabs - which is the recommended approach. I don't want to change my design and drop fragments simply because an older ver of the OS has a small stack.

I'm looking for ways to increase the stack size of the UI thread. I've seen answers that this is not possible, and I understand that there is no simple setting in the manifest to do so. But, I'm still not satisfied that there is no manual workaround.

My best idea thus far:

Create a new worker thread (Thread class) with a larger stack. It is possible to increase the stack size for worker threads. Then, transform this thread somehow to the new UI thread. How?

  • Browsing through the Android sources for android.app.Activity.attach(..) I've seen that an activity attaches itself to a UI thread. Maybe there is some way to replace the thread it is attached to and change it to my "new" UI thread

  • Going a little deeper to android.app.ActivityThread.startActivityNow(..), maybe I'll be able to start my activity manually. Once the activity is created, it attaches itself automatically to the thread it is created on. Maybe if I run this from my new UI thread, it will work.

  • If I create a new UI thread, I will have to manually create the Looper for it. I'm getting a sense of what's need to be created from android.app.ActivityThread.main(..)

Other ideas:

  • Catch the StackOverflowError manually and when it happens move calls asynchronously so they have a smaller stack. I've seen this nice idea here but I was unable to make it work.

  • NDK threads (via JNI) have large stacks. I thought about using them for my benefit but I see no way to do this. All calls via JNI are performed on their own thread so I can't see how I can use NDK threads for UI access.

So..

Except for saying that this is a very bad idea altogether, any other suggestions or tips? Can you find anyone who did something similar? I couldn't..

有帮助吗?

解决方案

CommonsWare is sadly mistaken. Closer inspection shows that the default stack size on Android 2.x is 12KB and in Android 4.x has been increased to 16KB. This means the core team was aware of the small stack issue and fixed it. Sad to say, but these extra 4KB is what makes all the difference in crashes.

Furthermore, if you are using common libraries like ABS and support v4 - these libraries add the extra views to your layout whenever you are using fragments. Since most of us rely on these libraries, saying that fragments can easily be added with 1 view is simply incorrect. If you are using ABS+support lib you will pay 3 views per fragment. And you will start off with a minimum of 5 views (for ABS layout).

Regarding creating a UI thread manually, this may be possible and will probably not require to root the device or change its firmware. These were also bold statements that are probably incorrect.

Finally, I've decided against creating my own UI thread with large stack. Instead, I've chosen to completely drop the use of fragments from my code. This saved me a total of 5 views in my layout. Everything that fragments give you, can also be done by adding ViewGroups manually. It's just a little more code, but nothing too complex. It seems that fragments are a little useless and if you don't have the luxury of using them - that's the first place to cut.

其他提示

On Android 4 everything is fine

No, you just haven't crashed yet. I am not aware that they increased the stack size on Android 4.x. They may have made some widgets a bit more efficient, which is allowing you to survive a bit longer, for some operations.

This is a problem because the large number of views is due to me using the support library and fragments for tabs - which is the recommended approach

You are welcome to use ordinary Views in tabs, whether those tabs are from ViewPager (and a suitable indicator), the action bar, or even the ancient TabHost. Fragments are not required.

I'm looking for ways to increase the stack size of the UI thread

This is not possible except by modifying the Android framework and forcing ~800 million Android device users at gunpoint to root their phones and replace their framework. Even if it were possible, unless you are in position to test on hundreds of devices, you will have no idea if your hack will be stable.

Anyways, being at 15 is still too much on the edge.. especially when nobody can tell exactly where the edge lies

The "edge" is 8KB of stack space, if I remember the figure correctly. Talented programmers realize that you cannot express the "edge" precisely in terms of the number of nested views in the hierarchy, as stack consumption will vary based on operations being performed and OS level.

I've seen so many people stuck with the same problem

You have a rather low value for "so many". This hasn't been a significant problem in years, based on questions asked in public support areas.

The tab fragment activity from the support library takes 5 views by itself.

Since there is nothing in Android named a "tab fragment activity", we cannot help you much with this, other than to suggest using another source of tabs. For example, ViewPager with TabPagerIndicator (from ViewPagerIndicator) should be around two nested levels along the critical path.

Then every fragment is at least 4.

Talented programmers realize that fragments do not even need to have views, and so the minimum number of views for a fragment is 0. Talented programmers also realize that fragments that do have a UI need a minimum of 1 view, not 4, because you can return any View you want from onCreateView() -- there is nothing in the semantics of onCreateView() that requires 4.

For example, this sample project uses a ViewPager with TabPagerIndicator and fragments for the tabs. From root to critical-path leaf, the entire structure has 7 levels.

Having 10 views in my personal hierarchy is nothing extraordinary

Yes, it is, once you add the 3 levels intrinsic to all activities, as 13 levels definitely start to make me nervous. In my cited example, ViewPager, its tabs, and the fragments add 4 levels on top of that. If you are saying that you want to have 10 levels of hierarchy in a tab, I doubt that there is a tab solution slim enough for that, though action bar tabs are one possibility.

Hence, your solution is:

  • Simplify your 10-level per-tab hierarchy
  • If that alone is insufficient, choose a slimmer tab implementation
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top