Android:增加调用堆栈大小

12

我的应用程序具有非常复杂的用户界面,其中包含许多嵌套在另一个中的布局。在创建另一个布局时,我遇到了一个StackOverflowError

我想知道原因,于是创建了两个测试示例:

1)Hello world应用程序,主Activity的xml如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <!-- ...So on 30 times... -->

                <FrameLayout
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent" >

                </FrameLayout>

            <!-- ...So on 30 times... -->

        </FrameLayout>
    </FrameLayout>
</FrameLayout>

当绘制布局时,会引发StackOverflowError(因为每个布局都会递归地绘制其子元素)。

2)以下是测试用例:

public class TestOverflowActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        overflow(0);
    }

    private void overflow(int i){
        android.util.Log.i("Stack depth:", " = " + i);
        overflow(i+1);
    }
}

在深度约为260-270次调用时会导致 StackOverflowError 错误。

对于第二个测试案例中的每个函数调用,栈元素会消耗4字节用于返回地址,+4字节用于参数,总共是8字节。虚拟机Dalvik可能会在每个元素中保存更多的信息,但即使每个元素占用 16字节* 260次调用=最大堆栈大小约为4K字节,这似乎还不够。

有没有办法增加最大堆栈大小?

3个回答

26

您可能无法在主UI线程中增加调用栈大小(这是可以理解的,因为您应该尽可能少地在此处执行操作),但您可以通过利用Thread对象的构造函数参数在单独的线程中完成它:

ThreadGroup group = new ThreadGroup("threadGroup");
new Thread(group, runnableObject, "YourThreadName", 2000000).start();

通过这个例子,我将我的堆栈大小从8k(大约260次调用)增加到2M(足够避免StackOverFlowException异常,当然你可以根据内存容量自由添加)。所以最终对于后来者,这就是你可以增加堆栈大小的方法。虽然不建议这样做,在某些情况下确实是必要的,例如具有广泛递归调用的算法,当然在工作线程中完成所有艰苦工作(正如您应该的那样),使用指定的堆栈大小并使用Handlers或任何您想使用的机制与主UI线程交互,只需“发布”UI更改即可...

希望能帮到你...

问候!


是的,我认为这是一个很好的答案,尽管我不认为它保证会遵守堆栈大小?如果可能的话,最好完全避免这种情况。 - Sean Owen

0
你绝对不想像那样嵌套布局。如果你发现自己嵌套了三到四次,那么视图的构建效率会越来越低,这可能会导致活动转换在视图创建之前开始并且很可能在你的情况下结束。这看起来很奇怪,或者是完全浪费了一个活动转换。
你应该将根布局设置为相对布局,并将所有的框架布局作为该根相对布局的子项。

-1
如果你需要这种复杂的布局(许多人可能会怀疑),你仍然可以在 onCreate 方法中程序化地绘制它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接