Die Art und Weise, wie Sie die Hierarchie Ihrer View
-Objekte verwalten, kann die Leistung Ihrer Anwendung erheblich beeinträchtigen. Auf dieser Seite wird beschrieben, wie Sie beurteilen können, ob Ihre Ansichtshierarchie die Anwendung verlangsamt. Außerdem werden einige Strategien zum Beheben von Problemen vorgestellt.
Auf dieser Seite geht es vorrangig um die Verbesserung von View
-basierten Layouts. Informationen zur Verbesserung der Jetpack Compose-Leistung finden Sie unter Jetpack Compose-Leistung.
Layout und Leistungsmessung
Die Rendering-Pipeline umfasst eine Layout-and-measure-Phase, in der das System die relevanten Elemente in Ihrer Ansichtshierarchie richtig positioniert. Der Teil measure dieser Phase bestimmt die Größe und Grenzen von View
-Objekten. Der Teil layout bestimmt, wo auf dem Bildschirm die View
-Objekte platziert werden.
Für beide Pipelinephasen fallen geringe Kosten pro Ansicht oder Layout an. In den meisten Fällen sind diese Kosten minimal und wirken sich nicht merklich auf die Leistung aus. Sie kann jedoch größer sein, wenn eine App View
-Objekte hinzufügt oder entfernt, z. B. wenn ein RecyclerView
-Objekt sie wiederverwendet oder wiederverwendet. Die Kosten können auch höher sein, wenn für ein View
-Objekt eine Größenanpassung erforderlich ist, um die Einschränkungen zu erfüllen. Wenn Ihre Anwendung beispielsweise SetText()
für ein View
-Objekt aufruft, das Text umbricht, muss möglicherweise die Größe des View
-Elements angepasst werden.
Wenn solche Fälle zu lange dauern, verhindern sie, dass ein Frame innerhalb der zulässigen 16 ms gerendert wird. Dies kann dazu führen, dass Frames ausfallen und Animationen verzögert angezeigt werden.
Da Sie diese Vorgänge nicht in einen Worker-Thread verschieben können, weil Ihre Anwendung sie im Hauptthread verarbeiten muss, sollten Sie sie so optimieren, dass sie so wenig Zeit wie möglich in Anspruch nehmen.
Komplexe Layouts verwalten
Mit Android-Layouts können Sie UI-Objekte in der Ansichtshierarchie verschachteln. Diese Verschachtelung kann auch Layoutkosten verursachen. Wenn Ihre App ein Objekt für das Layout verarbeitet, führt sie denselben Prozess auch für alle untergeordneten Elemente des Layouts durch.
Bei einem komplizierten Layout fallen manchmal Kosten nur dann an, wenn das System das Layout zum ersten Mal berechnet. Wenn Ihre Anwendung beispielsweise ein komplexes Listenelement in einem RecyclerView
-Objekt wiederverwendet, muss das System alle Objekte neu anordnen. In einem anderen Beispiel können sich triviale Änderungen in der Kette nach oben in Richtung des übergeordneten Elements ausbreiten, bis sie ein Objekt erreichen, das sich nicht auf die Größe des übergeordneten Elements auswirkt.
Ein häufiger Grund dafür, dass das Layout lange dauert, ist, dass Hierarchien von View
-Objekten ineinander verschachtelt sind. Durch jedes verschachtelte Layoutobjekt fallen Kosten für die Layoutphase an. Je flacher Ihre Hierarchie ist, desto weniger Zeit dauert die Ausführung der Layoutphase.
Wir empfehlen, ein ConstraintLayout
statt mit RelativeLayout
oder LinearLayout
mit dem Layout-Editor zu erstellen, da dies im Allgemeinen effizienter ist und die Verschachtelung von Layouts reduziert. Für einfache Layouts, die mit FrameLayout
erreicht werden können, empfehlen wir jedoch die Verwendung von FrameLayout
.
Wenn Sie die Klasse RelativeLayout
verwenden, können Sie möglicherweise denselben Effekt bei geringeren Kosten erzielen, wenn Sie stattdessen verschachtelte, ungewichtete LinearLayout
-Ansichten verwenden. Wenn Sie jedoch verschachtelte, gewichtete LinearLayout
-Ansichten verwenden, sind die Layoutkosten viel höher, da dafür mehrere Layoutdurchläufe erforderlich sind, wie im nächsten Abschnitt erläutert.
Außerdem empfehlen wir die Verwendung von RecyclerView
anstelle von ListView
. Dadurch können die Layouts einzelner Listenelemente wiederverwendet werden. Das ist nicht nur effizienter, sondern kann auch die Scrollleistung verbessern.
Doppelte Besteuerung
In der Regel führt das Framework das Layout oder die Messungsphase in einem einzigen Durchlauf aus. Bei einigen komplizierten Layoutfällen muss das Framework jedoch möglicherweise mehrere Teile der Hierarchie iterieren, für die mehrere Durchgänge erforderlich sind, bevor die Elemente schließlich positioniert werden. Die Vorgabe mehrerer Layout- und Messdurchläufe wird als doppelte Besteuerung bezeichnet.
Wenn Sie beispielsweise den RelativeLayout
-Container verwenden, mit dem Sie View
-Objekte in Bezug auf die Positionen anderer View
-Objekte positionieren können, führt das Framework die folgende Sequenz aus:
- Führt einen Layout- und Messwertdurchlauf aus, bei dem das Framework die Position und Größe jedes untergeordneten Objekts basierend auf der Anfrage jedes untergeordneten Objekts berechnet.
- Nutzt diese Daten unter Berücksichtigung der Objektgewichte, um die richtige Position korrelierter Ansichten zu ermitteln.
- Führt einen zweiten Layoutübergang aus, um die Positionen der Objekte abzuschließen.
- Die nächste Phase des Renderingprozesses wird erreicht.
Je mehr Ebenen die Ansichtshierarchie aufweist, desto höher ist die Gefahr von Leistungseinbußen.
Wie bereits erwähnt, ist ConstraintLayout
im Allgemeinen effizienter als andere Layouts außer FrameLayout
. Es ist weniger anfällig für mehrere Layoutdurchläufe und in vielen Fällen ist es nicht erforderlich, Layouts zu verschachteln.
Andere Container als RelativeLayout
können ebenfalls die Doppelbesteuerung erhöhen. Beispiel:
- Eine
LinearLayout
-Ansicht kann bei horizontaler Darstellung zu einem doppelten Layout- und Messungsdurchlauf führen. Wenn dumeasureWithLargestChild
hinzufügst, kann das Framework auch bei einer vertikalen Ausrichtung einen doppelten Durchlauf und einen zweiten Durchgang durchlaufen. - Der
GridLayout
ermöglicht zwar auch eine relative Positionierung, vermeidet jedoch doppelte Besteuerung, indem die Positionsbeziehungen zwischen untergeordneten Ansichten vorverarbeitet werden. Wenn im Layout jedoch Gewichtungen oder Füllungen mit der KlasseGravity
verwendet werden, geht der Vorteil der Vorverarbeitung verloren und das Framework muss möglicherweise mehrere Durchgänge ausführen, wenn der Container einRelativeLayout
ist.
Mehrere Durchgänge für Layout und Messung stellen nicht unbedingt eine Leistungsbeeinträchtigung dar. Sie können jedoch zu einer Belastung werden, wenn sie sich am falschen Ort befinden. Seien Sie vorsichtig, wenn eine der folgenden Bedingungen auf Ihren Container zutrifft:
- Es ist ein Stammelement in Ihrer Ansichtshierarchie.
- Unter ihr befindet sich eine tiefgehende Ansichtshierarchie.
- Es wird in vielen Fällen auf dem Bildschirm dargestellt, ähnlich wie Kinder in einem
ListView
-Objekt.
Probleme in der Ansichtshierarchie diagnostizieren
Die Layoutleistung ist ein komplexes Problem mit vielen Facetten. Mit den folgenden Tools können Sie feststellen, wo Leistungsengpässe auftreten. Einige Tools liefern weniger konkrete Informationen, können aber hilfreiche Tipps geben.
Perfetto
Perfetto ist ein Tool, das Daten zur Leistung bereitstellt. Sie können Android-Traces in der Perfetto-UI öffnen.
GPU-Rendering für Profil
Das On-Device-Tool für das Profil-GPU-Rendering, das auf Geräten mit Android 6.0 (API-Level 23) und höher verfügbar ist, kann Ihnen konkrete Informationen zu Leistungsengpässen liefern. Mit diesem Tool kannst du sehen, wie lange die Phase "Layout and Measure" für jeden Rendering-Frame dauert. Anhand dieser Daten lassen sich Probleme mit der Laufzeitleistung diagnostizieren und so ermitteln, welche Layout- und Messprobleme Sie beheben müssen.
Bei der grafischen Darstellung der erfassten Daten verwendet das Profil-GPU-Rendering die Farbe Blau, um die Layoutzeit darzustellen. Weitere Informationen zur Verwendung dieses Tools finden Sie unter Profil-GPU-Renderinggeschwindigkeit.
Fussel
Das Lint-Tool von Android Studio kann Ihnen ein Gefühl für die Ineffizienzen in der Ansichtshierarchie verschaffen. Wählen Sie Analysieren > Code prüfen aus, um dieses Tool zu verwenden, wie in Abbildung 1 dargestellt.
Informationen zu verschiedenen Layoutelementen finden Sie unter Android > Lint > Leistung. Klicken Sie auf die einzelnen Elemente, um sie zu maximieren und weitere Informationen im Bereich auf der rechten Seite des Bildschirms anzuzeigen. Abbildung 2 zeigt ein Beispiel für erweiterte Informationen.
Wenn Sie auf ein Element klicken, werden im Bereich rechts die damit verbundenen Probleme angezeigt.
Weitere Informationen zu bestimmten Themen und Problemen in diesem Bereich finden Sie in der Lint-Dokumentation.
Layout Inspector
Das Tool Layout Inspector von Android Studio bietet eine visuelle Darstellung der Ansichtshierarchie Ihrer App. Sie bietet eine gute Möglichkeit, sich in der Hierarchie Ihrer App zurechtzufinden. Sie bietet eine klare visuelle Darstellung der übergeordneten Kette einer bestimmten Ansicht und ermöglicht es Ihnen, die von Ihrer App erstellten Layouts zu überprüfen.
Die vom Layout Inspector präsentierten Ansichten können auch dabei helfen, Leistungsprobleme aufgrund von doppelter Besteuerung zu erkennen. Sie können damit auch tiefe Ketten verschachtelter Layouts oder Layoutbereiche mit vielen verschachtelten untergeordneten Elementen identifizieren, was zu Leistungskosten führen kann. In diesen Fällen können die Layout- und Messphasen kostspielig sein und zu Leistungsproblemen führen.
Weitere Informationen finden Sie unter Layoutfehler mit Layout Inspector und Layout Validation beheben.
Probleme mit der Ansichtshierarchie beheben
Das grundlegende Konzept der Lösung von Leistungsproblemen, die aus Ansichtshierarchien entstehen, kann in der Praxis schwierig sein. Wenn Sie verhindern möchten, dass durch Ansichtshierarchien Leistungseinbußen verhängt werden, wird die Ansichtshierarchie vereinfacht und Doppelbesteuerungen reduziert. In diesem Abschnitt werden Strategien besprochen, um diese Ziele zu erreichen.
Redundante verschachtelte Layouts entfernen
ConstraintLayout
ist eine Jetpack-Bibliothek mit einer Vielzahl verschiedener Mechanismen zur Positionierung von Ansichten im Layout. Dadurch ist kein Verschachteln von ConstaintLayout
erforderlich und die Ansichtshierarchie wird vereinfacht. Es ist normalerweise einfacher, Hierarchien mit ConstraintLayout
im Vergleich zu anderen Layouttypen abzuflachen.
Entwickler verwenden oft mehr verschachtelte Layouts als nötig. Beispielsweise kann ein RelativeLayout
-Container ein einzelnes untergeordnetes Element enthalten, das auch ein RelativeLayout
-Container ist. Diese Verschachtelung ist redundant und verursacht unnötige Kosten für die Ansichtshierarchie. Lint kann dieses Problem für Sie melden und so die Fehlerbehebungszeit verkürzen.
Zusammenführung übernehmen oder einschließen
Eine häufige Ursache für redundante verschachtelte Layouts ist das Tag <include>
. Ein wiederverwendbares Layout könnte beispielsweise so definiert werden:
<LinearLayout> <!-- some stuff here --> </LinearLayout>
Anschließend können Sie ein <include>
-Tag hinzufügen, um dem übergeordneten Container das folgende Element hinzuzufügen:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg" android:gravity="center_horizontal"> <include layout="@layout/titlebar"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" /> ... </LinearLayout>
Beim obigen Beispiel wird das erste Layout unnötigerweise im zweiten Layout verschachtelt.
Mit dem Tag <merge>
lässt sich dieses Problem vermeiden. Informationen zu diesem Tag finden Sie unter <merge>-Tag verwenden.
Ein günstigeres Layout verwenden
Möglicherweise können Sie Ihr vorhandenes Layoutschema nicht so anpassen, dass es keine redundanten Layouts enthält. In bestimmten Fällen kann die einzige Lösung darin bestehen, die Hierarchie zu vereinfachen, indem Sie zu einem völlig anderen Layouttyp wechseln.
Sie könnten beispielsweise feststellen, dass TableLayout
die gleiche Funktionalität wie ein komplexeres Layout mit vielen Positionsabhängigkeiten bietet. Die Jetpack-Bibliothek ConstraintLayout
bietet ähnliche Funktionen wie RelativeLayout
sowie weitere Funktionen zum Erstellen einfacherer, effizienterer Layouts.