Android: увеличить размер стека вызовов - PullRequest
11 голосов
/ 14 января 2012

У меня есть приложение с очень сложным пользовательским интерфейсом, содержащее множество layouts, вложенных друг в друга. При создании другого макета я поймал StackOverflowError

Интересно, я создал два тестовых примера:

1) Привет, мир, приложение со следующим 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);
    }
}

вызывает StackOverflowError на глубине около 260-270 вызовов.

Каждый вызов элемента стека для второго контрольного примера занимает 4 байта для адреса возврата + 4 bytes для параметра = 8 bytes. Возможно, что Dalvik's VM хранит немного больше информации в каждом элементе, но даже 16 bytes per element * 260 calls = about 4Kbytes для максимального общего размера стека. Этого не достаточно.

Есть ли способ увеличить максимальный размер стека?

Ответы [ 3 ]

25 голосов
/ 14 ноября 2013

Возможно, вам не удастся увеличить размер стека вызовов в основном потоке пользовательского интерфейса (что понятно, потому что вы должны делать как можно меньше вещей здесь), но вы можете сделать это в отдельном потоке, используяпараметры конструктора объекта Thread:

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

В этом примере я увеличил размер своего стека с 8 КБ (около 260 вызовов) до 2 МБ (достаточно, чтобы не получить исключение StackOverFlowException, конечно, вы можете добавить столько, сколько вам нужнодо тех пор, пока память может ее занять), поэтому, в конце концов, для дальнейших читателей, это способ увеличить размер стека, хотя это и не рекомендуется, в некоторых случаях это действительно необходимо, например, алгоритм с обширными рекурсивными вызовамии, конечно же, выполняя всю тяжелую работу в рабочем потоке (как и положено) с указанным размером стека и просто «публикуя» изменения в пользовательском интерфейсе, используя основной поток пользовательского интерфейса с обработчиками или любой другой механизм, который вы хотели бы использовать длявзаимодействовать с ним ...

Надеюсь, это поможет ...

RegarDS!

0 голосов
/ 09 марта 2016

Вы определенно не хотите вкладывать макеты друг в друга, как это.Если вы обнаружите, что вкладываете три или четыре раза, то построение представления становится все менее и менее эффективным, что может привести к тому, что переходы действий начнутся и, возможно, в вашем случае завершатся до создания представления.Это будет выглядеть странно или будет пустой тратой перехода активности.

Вы должны сделать свой корневой макет относительным макетом и иметь все свои макеты фреймов в качестве дочерних элементов этого корневого относительного макета.

0 голосов
/ 15 января 2012

Если вам нужен этот сложный макет (как многие сомневаются), вы все равно можете нарисовать его программно в методе onCreate.

...