Создайте поток пользовательского интерфейса вручную в Android, чтобы увеличить его размер небольшого стека

Я борюсь с StackOverflowErrors в основном потоке пользовательского интерфейса ( связанный вопрос ). Мое приложение предназначено для Android 2.3+. На Android 4 все в порядке, но я получаю сбои в 2.3.3, когда макет представления рисуется.

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

Я ищу способы увеличить размер стека потока пользовательского интерфейса. Я видел ответы, что это невозможно, и я понимаю, что в манифесте нет простой настройки для этого. Но я все еще не удовлетворен тем, что нет ручного решения.

Моя лучшая идея:

Создайте новый рабочий поток (класс Thread) с большим стеком. Можно увеличить размер стека для рабочих потоков. Затем преобразуйте этот поток как-то в новый поток пользовательского интерфейса. Как?

  • Просмотр через Android-файлы android.app.Activity .attach (..) Я видел, что активность присоединяется к потоку пользовательского интерфейса. Возможно, есть способ заменить поток, к которому он прикреплен, и изменить его на мой «новый» поток пользовательского интерфейса

  • Идя немного глубже в android.app.ActivityThread .startActivityNow (..), возможно, я смогу начать свою деятельность вручную. После создания активности он автоматически привязывается к потоку, на котором он создан. Возможно, если я запустил это из своего нового потока пользовательского интерфейса, он будет работать.

  • Если я создам новый поток пользовательского интерфейса, мне придется вручную создать Looper для него. Я получаю представление о том, что нужно создать из android.app.ActivityThread .main (..)

Другие идеи:

  • Поймайте StackOverflowError вручную, и когда это произойдет, переходы вызываются асинхронно, поэтому они имеют меньший стек. Я видел эту прекрасную идею здесь, но я не смог заставить ее работать.

  • Нити NDK (через JNI) имеют большие стеки. Я думал об использовании их в свою пользу, но я не вижу возможности сделать это. Все вызовы через JNI выполняются в собственном потоке, поэтому я не вижу, как я могу использовать потоки NDK для доступа к пользовательскому интерфейсу.

Так..

Кроме того, что это совсем плохая идея, любые другие предложения или советы? Можете ли вы найти любого, кто сделал что-то подобное? Я не мог ..

Solutions Collecting From Web of "Создайте поток пользовательского интерфейса вручную в Android, чтобы увеличить его размер небольшого стека"

CommonsWare печально ошибается. Более тщательная проверка показывает, что размер стека по умолчанию на Android 2.x составляет 12 КБ, а в Android 4.x увеличен до 16 КБ. Это означает, что основная команда была осведомлена о проблеме с небольшим стеком и исправила ее. Грустно сказать, но эти дополнительные 4KB – это то, что делает всю разницу в авариях.

Кроме того, если вы используете общие библиотеки, такие как ABS и support v4, эти библиотеки добавляют дополнительные представления к вашему макету всякий раз, когда вы используете фрагменты. Поскольку большинство из нас полагается на эти библиотеки, говоря, что фрагменты могут быть легко добавлены с 1 представлением, просто неверны. Если вы используете библиотеку поддержки ABS +, вы заплатите 3 просмотра за фрагмент. И вы начнете с минимум 5 просмотров (для макета АБС).

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

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

На Android 4 все в порядке

Нет, вы просто не разбились. Я не знаю, что они увеличили размер стека на Android 4.x. Возможно, они сделали некоторые виджеты более эффективными, что позволяет вам выжить немного дольше для некоторых операций.

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

Вы можете использовать обычные Views в вкладках, независимо от того, находятся ли эти вкладки из ViewPager (и подходящего индикатора), панели действий или даже древней TabHost . Фрагменты не требуются.

Я ищу способы увеличить размер стека потока пользовательского интерфейса

Это невозможно, кроме как путем изменения рамок Android и принуждения ~ 800 миллионов пользователей устройств Android под прицелом, чтобы укоренить свои телефоны и заменить их рамки. Даже если бы это было возможно, если вы не в состоянии проверить на сотнях устройств, вы не будете знать, будет ли ваш хак стабильным.

В любом случае, будучи в 15, все еще слишком много на краю .. особенно когда никто не может точно сказать, где лежит край

«Край» составляет 8 Кбайт пространства стека, если я правильно помню цифру. Талантливые программисты понимают, что вы не можете выразить «край» именно с точки зрения количества вложенных представлений в иерархии, так как потребление стека будет варьироваться в зависимости от выполняемых операций и уровня ОС.

Я видел, как многие люди сталкивались с одной и той же проблемой

У вас довольно низкое значение для «очень многих». Это не было значительной проблемой в течение многих лет, основываясь на вопросах, заданных в областях общественной поддержки.

Активность фрагмента вкладки из библиотеки поддержки принимает 5 представлений сама по себе.

Поскольку в Android нет ничего «активности фрагментов вкладок», мы не можем вам помочь с этим, кроме того, чтобы предлагать использовать другой источник вкладок. Например, ViewPager с TabPagerIndicator (из ViewPagerIndicator ) должен находиться вокруг двух вложенных уровней вдоль критического пути.

Тогда каждый фрагмент не менее 4.

Талантливые программисты понимают, что фрагментам даже не нужны представления, поэтому минимальное количество просмотров для фрагмента равно 0. Талантливые программисты также понимают, что фрагменты, имеющие пользовательский интерфейс, должны иметь минимум 1 вид, а не 4, потому что вы можете Return any View вы хотите от onCreateView() – в семантике onCreateView() нет ничего, что требует 4.

Например, этот примерный проект использует ViewPager с TabPagerIndicator и фрагменты для вкладок. От корня до листа критического пути вся структура имеет 7 уровней.

Имея 10 взглядов в моей личной иерархии, нет ничего экстраординарного

Да, это так, как только вы добавите 3 уровня, присущие всем действиям, поскольку 13 уровней определенно начинают меня нервничать. В приведенном выше примере ViewPager , его вкладки и фрагменты добавляют к нему 4 уровня. Если вы говорите, что хотите, чтобы на вкладке было 10 уровней иерархии, я сомневаюсь, что для нее достаточно тонкое решение табуляции, хотя вкладки панели действий – одна из возможностей.

Следовательно, ваше решение:

  • Упростите свою 10-уровневую иерархию за вкладку
  • Если этого недостаточно, выберите более тонкую реализацию вкладки