Ich habe Probleme mit StackOverflowErrors im Hauptthread der Benutzeroberfläche ( verwandte Frage ). Meine App zielt auf Android 2.3+. Auf Android 4 ist alles in Ordnung, aber ich bekomme Abstürze auf 2.3.3, wenn das Ansichtslayout gezeichnet wird.
Die offensichtliche Antwort besteht darin, mein Ansichtslayout zu optimieren und die Anzahl verschachtelter Ansichten zu reduzieren. Dies ist ein Problem, da die große Anzahl von Ansichten darauf zurückzuführen ist, dass ich die Support-Bibliothek und Fragmente für Tabs verwende - was der empfohlene Ansatz ist. Ich möchte mein Design nicht ändern und Fragmente einfach deshalb ablegen, weil ein älteres ver der OS einen kleinen Stapel hat.
Ich suche nach Möglichkeiten, die Stapelgröße des UI-Threads zu erhöhen. Ich habe Antworten gesehen, dass dies nicht möglich ist, und ich verstehe, dass es im Manifest keine einfache Einstellung dafür gibt . Aber ich bin immer noch nicht überzeugt, dass es keine manuelle Problemumgehung gibt.
Meine bisher beste Idee:
Erstellen Sie einen neuen Arbeitsthread (Thread-Klasse) mit einem größeren Stapel. Es ist möglich, die Stapelgröße für Worker-Threads zu erhöhen. Verwandle diesen Thread dann irgendwie in den neuen UI-Thread. Wie?
Durchsuchen Sie die Android-Quellen nach android.app.Activity .attach (..) Ich habe gesehen, dass sich eine Aktivität an einen UI-Thread anhängt. Vielleicht gibt es eine Möglichkeit, den Thread zu ersetzen, an den es angehängt ist, und es zu meinem "neuen" UI-Thread zu ändern
Ein wenig tiefer geht es zu android.app.ActivityThread .startActivityNow (..), vielleicht kann ich meine Aktivität manuell starten. Sobald die Aktivität erstellt wurde, hängt sie sich automatisch an den Thread an, auf dem sie erstellt wurde. Wenn ich das von meinem neuen UIhread aus starte, funktioniert es vielleicht.
Wenn ich einen neuen UI-Thread erstelle, muss ich den Looper manuell dafür erstellen. Ich verstehe, was erstellt werden muss. android.app.ActivityThread .main (..)
Andere Ideen:
Fangen Sie StackOverflowError manuell ab, und wenn dies geschieht, werden Aufrufe asynchron ausgeführt, sodass sie einen kleineren Stack haben. Ich habe diese nette Idee hier gesehen, aber ich konnte es nicht zum Laufen bringen .
NDK-Threads (über JNI) haben große Stacks. Ich dachte daran, sie zu meinem Vorteil zu nutzen, aber ich sehe keinen Weg, dies zu tun. Alle Aufrufe über JNI werden auf ihrem eigenen Thread ausgeführt, sodass ich nicht sehen kann, wie ich NDK-Threads für den UI-Zugriff verwenden kann.
Also ..
Abgesehen davon, dass das eine sehr schlechte Idee ist, irgendwelche anderen Vorschläge oder Tipps? Kannst du jemanden finden, der etwas Ähnliches getan hat? Ich konnte nicht ..
CommonsWare ist leider falsch. Eine genauere Überprüfung zeigt, dass die standardmäßige Stackgröße auf Android 2.x 12 KB und in Android 4.x auf 16 KB erhöht wurde. Dies bedeutet, dass das Kernteam das Problem des kleinen Stapels erkannt und behoben hat. Traurig zu sagen, aber diese zusätzlichen 4 KB macht den Unterschied in Abstürzen.
Wenn Sie allgemeine Bibliotheken wie ABS und support v4 verwenden, fügen diese Bibliotheken außerdem die zusätzlichen Ansichten zu Ihrem Layout hinzu, wenn Sie Fragmente verwenden. Da die meisten von uns auf diese Bibliotheken angewiesen sind, ist es einfach falsch zu sagen, dass Fragmente einfach mit einer Ansicht hinzugefügt werden können. Wenn Sie ABS + support lib verwenden, zahlen Sie 3 Aufrufe pro Fragment. Und Sie beginnen mit mindestens 5 Ansichten (für ABS-Layout).
In Bezug auf das manuelle Erstellen eines UI-Threads ist dies möglicherweise möglich und wird wahrscheinlich nicht erforderlich sein, um das Gerät zu rooten oder seine Firmware zu ändern. Dies waren auch kühne Aussagen, die wahrscheinlich falsch sind.
Schließlich habe ich mich gegen die Erstellung eines eigenen UI-Threads mit großem Stack entschieden. Stattdessen habe ich entschieden, die Verwendung von Fragmenten vollständig aus meinem Code zu entfernen. Das hat mir insgesamt 5 Ansichten in meinem Layout gerettet. Alles, was Ihnen Fragmente liefern, können Sie auch manuell durch Hinzufügen von ViewGroups erreichen. Es ist nur ein wenig mehr Code, aber nichts zu komplex. Es scheint, dass Fragmente ein wenig nutzlos sind, und wenn Sie nicht den Luxus haben, sie zu benutzen - das ist der erste Platz, um zu schneiden.
Auf Android 4 ist alles in Ordnung
Nein, du bist noch nicht abgestürzt. Mir ist nicht bewusst, dass sie die Stapelgröße auf Android 4.x erhöht haben. Sie könnten einige Widgets ein wenig effizienter gemacht haben, was es Ihnen ermöglicht, für einige Operationen ein wenig länger zu überleben.
Dies ist ein Problem, weil die große Anzahl von Ansichten auf die Verwendung der Support-Bibliothek und Fragmente für Tabs zurückzuführen ist - was der empfohlene Ansatz ist.
Sie können gerne das normale Views
in Tabs verwenden, unabhängig davon, ob diese Tabs von ViewPager
(und einem geeigneten Indikator), der Aktionsleiste oder sogar dem alten TabHost
stammen. Fragmente sind nicht erforderlich.
Ich suche nach Möglichkeiten, die Stapelgröße des UI-Threads zu erhöhen
Dies ist nur möglich, wenn das Android-Framework geändert wird und 800 Millionen Android-Gerätebenutzer mit vorgehaltener Waffe gezwungen werden, ihre Telefone zu rooten und ihr Framework zu ersetzen. Selbst wenn es möglich wäre, wenn du nicht in der Lage bist, auf hunderten von Geräten zu testen, wirst du keine Ahnung haben, ob dein Hack stabil sein wird.
Wie auch immer, bei 15 zu sein ist immer noch zu sehr am Rand ... vor allem, wenn niemand genau sagen kann, wo die Kante liegt
Die "Kante" ist 8KB Stapelplatz, wenn ich mich an die Figur richtig erinnere. Talentierte Programmierer erkennen, dass Sie die "Kante" nicht genau in Bezug auf die Anzahl der verschachtelten Ansichten in der Hierarchie ausdrücken können, da die Stapelkonsum abhängig von den ausgeführten Vorgängen und der Betriebssystemebene variiert.
Ich habe so viele Leute gesehen, die mit dem gleichen Problem stecken geblieben sind
Sie haben einen eher niedrigen Wert für "so viele". Dies ist seit Jahren kein bedeutendes Problem, basierend auf Fragen, die in öffentlichen Unterstützungsbereichen gestellt wurden.
Die Tab-Fragment-Aktivität aus der Support-Bibliothek hat 5 Ansichten für sich.
Da in Android nichts als "Tab-Fragment-Aktivität" bezeichnet wird, können wir Ihnen nicht weiter helfen, als eine andere Tab-Quelle zu empfehlen. Zum Beispiel sollte ViewPager
mit TabPagerIndicator
(von ViewPagerIndicator ) ungefähr zwei verschachtelte Ebenen entlang des kritischen Pfads sein.
Dann ist jedes Fragment mindestens 4.
Talentierte Programmierer erkennen, dass Fragmente nicht einmal > Ansichten haben müssen, und so ist die minimale Anzahl von Sichten für ein Fragment 0. Talentierte Programmierer erkennen auch, dass Fragmente, die eine UI haben, ein Minimum benötigen von 1 Ansicht, nicht 4, weil Sie% View
von onCreateView()
zurückgeben können - es gibt nichts in der Semantik von onCreateView()
, das 4 erfordert.
Beispiel: Dieses Beispielprojekt verwendet ViewPager
mit TabPagerIndicator
und Fragmente für die Tabs. Von der Wurzel bis zum Blatt des kritischen Pfads hat die gesamte Struktur 7 Ebenen.
10 Ansichten in meiner persönlichen Hierarchie zu haben, ist nichts Außergewöhnliches
Ja, ist es, sobald Sie die 3 Ebenen, die allen Aktivitäten innewohnen, hinzufügen, da 13 Stufen mich definitiv nervös machen. In meinem zitierten Beispiel addieren ViewPager
, seine Tabs und die Fragmente zusätzlich 4 Ebenen. Wenn Sie sagen, dass Sie 10 Ebenen der Hierarchie in einem Tab haben wollen, bezweifle ich, dass es eine Tab-Lösung gibt, die dünn genug dafür ist, obwohl Aktionsleisten-Tabs eine Möglichkeit sind.
Daher lautet Ihre Lösung:
Tags und Links android android-sdk-2.3