Android:增加调用堆栈大小

时间:2012-01-13 21:41:31

标签: android stack-overflow

我的应用程序具有非常复杂的UI,其中包含许多layouts嵌套的应用程序。在创建另一个布局时,我抓住了StackOverflowError

想知道,我已经创建了两个测试示例:

1)以下xml主活动

的Hello world应用程序
<?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);
    }
}

导致StackOverflowError深度约260-270次调用。

第二个测试用例的每个stack元素调用都需要4个字节作为参数+ 4 bytes的返回地址= 8 bytesDalvik's VM可能会在每个元素中保留更多信息,但即使16 bytes per element * 260 calls = about 4Kbytes也可以获得最大的整体堆栈大小。这似乎不够。

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

3 个答案:

答案 0 :(得分:25)

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

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

通过这个例子,我的堆栈大小从8k(大约260个调用)增加到2M(足以不得到StackOverFlowException,当然你可以根据需要添加尽可能多的内存),所以最后,对于进一步的读者来说,这是你可以增加堆栈大小的方法,虽然不推荐,但在某些情况下,它实际上是必要的,例如一个带有大量递归调用的算法,当然还有通过在工作者中完成所有艰苦的工作使用您指定的堆栈大小的线程(如您所愿),并使用主要UI线程与处理程序或您希望用于与其交互的任何机制在UI中“发布”更改...

希望这有助于......

问候!

答案 1 :(得分:0)

您绝对不希望将布局嵌套在彼此内部。如果您发现自己嵌套了三到四次,那么视图的构造变得越来越低效,这可能导致活动转换开始,并且可能在您创建视图之前完成。这看起来很奇怪,或完全浪费了活动过渡。

您应该将根布局设为相对布局,并将所有框架布局作为该根相对布局的子项。

答案 2 :(得分:-1)

如果您需要这种复杂的布局(很多人会怀疑),您仍然可以在onCreate方法中绘制它。