Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create the UI thread manually in Android in order to increase its small stack size

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

like image 281
talkol Avatar asked Jun 04 '13 08:06

talkol


1 Answers

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.

like image 84
talkol Avatar answered Sep 21 '22 02:09

talkol