什么是android UI线程堆栈大小限制以及如何克服它?

tal*_*kol 26 android

我正在绘制视图层次结构时收到java.lang.StackOverflowErrors:

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)
...
Run Code Online (Sandbox Code Playgroud)

研究指出我的视图层次结构太深,Android无法处理.实际上,使用Hierarchy Viewer,我可以看到我最长的嵌套是19个视图(!)

我的应用看起来有点像Google Play商店应用(带滑动标签).每个选项卡都是片段视图寻呼机内的嵌套片段 - 使用v4支持和HoloEverywhere.显然,这就是我的等级制度有点疯狂的原因.

我的问题:

  1. 什么是真正的堆栈大小限制?我发现无法测量UI线程的堆栈大小.网上有传闻说8KB,但有没有办法在一些样本设备上准确测量?

  2. 堆栈大小限制是否随OS ver而变化?同一层级并没有崩溃的4.0.3设备上但并崩溃上的2.3.3设备(相同的硬件).这是为什么?

  3. 除了手动优化层次结构外,还有其他方案吗?我发现无法增加UI线程的可笑小堆栈.对不起,但60-100堆栈帧限制是一个笑话.

  4. 假设#3上没有奇迹解决方案,那么应该针对核心层次结构优化的哪些建议进行推荐?

  5. 疯狂的想法 - 我注意到每个视图层添加了大约3个函数调用(View.draw,ViewGroup.dispatchDraw,ViewGroup.drawChild).也许我可以创建自己的ViewGroup实现(自定义布局),在draw()期间在堆栈上浪费更少?

tal*_*kol 26

我相信主线程的堆栈是由JVM控制的 - 在Android的情况下 - Dalvik JVM.如果我没有弄错的相关常数可以在dalvik/vm/Thread.h下面找到#define kDefaultStackSize

通过dalvik源历史浏览堆栈大小:

那么你可以拥有多少嵌套视图:

无法准确说出来.假设堆栈大小如上所述,这一切都取决于您最深嵌套中的函数调用次数(以及每个函数需要多少个变量等).似乎有问题的区域是在绘制视图时,从开始android.view.ViewRoot.draw().每个视图都会调用其子项的绘制,并且它会与您最深的嵌套一样深.

我至少会对上面所有边界组中出现的设备进行经验测试.似乎使用模拟器可以得到准确的结果(尽管我只将原生x86模拟器与真实设备进行了比较).

请记住,优化实际小部件/布局的方式也可能会影响这一点.话虽如此,我相信每个布局层次结构都会占用大部分堆栈空间,增加了大约3个嵌套函数调用:draw()- > dispatchDraw()- > drawChild()这个设计从2.3到4.2没有太大变化.

  • 根据http://developer.android.com/guide/practices/verifying-apps-art.html,在Android 4.4中它是32KB (2认同)