Element Tree ist eine Zwischenschicht in Flutter, die den deklarativen Widget Tree mit dem imperativen RenderObject Tree verbindet. Im Gegensatz zu Widgets, die bei jedem Neubau neu erstellt werden, bleiben Elemente zwischen Updates bestehen und verwalten Zustand, Schlüssel und Lebenszyklus. Laut Flutter API Reference, 2025 ist das Verständnis von Element Tree für die effektive Arbeit mit Schlüsseln, Leistungsoptimierung und das Debuggen unerwarteten Widget-Verhaltens unerlässlich.
Wichtige Punkte
Element Tree ist eine Zwischenhierarchie in Flutter, die auf Basis des Widget Tree erstellt wird und die Einfügung von Widgets in die Anwendung verwaltet. Jede Elementinstanz entspricht einem Widget im Baum und speichert eine Referenz darauf. Der Hauptunterschied zwischen einem Element und einem Widget besteht darin, dass das Element seine Position im Baum zwischen Neubauten beibehält, während das Widget bei jedem build-Aufruf neu erstellt werden kann.
Ohne Element Tree könnte Flutter die Benutzeroberfläche nicht effizient aktualisieren. Wenn jeder Neubau den RenderObject Tree neu erstellen würde, wäre die Leistung inakzeptabel niedrig. Element Tree fungiert als Stabilisator: Er behält Referenzen auf RenderObject und State zwischen Updates bei und ermöglicht es Flutter, nur minimale Änderungen am Render-Baum vorzunehmen.
Flutter verwendet drei Haupttypen von Elementen: StatelessElement für StatelessWidget, StatefulElement für StatefulWidget und LeafRenderObjectElement, SingleChildRenderObjectElement, MultiChildRenderObjectElement für RenderObjectWidget. Jeder Typ ist auf seine Widget-Klasse spezialisiert und bestimmt, wie das Element mit RenderObject interagiert.
Die Drei-Schichten-Architektur von Flutter besteht aus Widget Tree (Konfiguration), Element Tree (Verwaltung) und RenderObject Tree (Rendering). Element Tree ist das verbindende Glied: Er liest die Konfiguration aus dem Widget und übergibt Befehle an RenderObject. Ohne Element Tree könnte das Framework die deklarative Beschreibung nicht effizient mit dem tatsächlichen Rendering synchronisieren.
Wenn ein Element in den Baum eingefügt wird, überprüft es den Widget-Typ. Wenn das Widget ein RenderObjectWidget ist, erstellt das Element das entsprechende RenderObject und fügt es in den RenderObject Tree ein. Wenn das Widget ein LeafRenderObjectWidget ist, erstellt das Element ein Blatt-RenderObject. Für StatelessWidget und StatefulWidget verwaltet das Element lediglich die Einfügung von Kind-Elementen.
abstract class Element {
Widget widget;
Element? parent;
List<Element>? children;
void mount(Element? parent, dynamic newSlot);
void update(Widget newWidget);
void unmount();
}
Dieser vereinfachte Code zeigt die grundlegende Struktur von Element. Jedes Element speichert eine Referenz auf das aktuelle Widget, das übergeordnete Element und die Kind-Elemente. Die Methoden mount, update und unmount verwalten den Lebenszyklus des Elements und seines zugehörigen RenderObject.
Jedes Element in Flutter durchläuft eine Abfolge von Lebenszyklusphasen: Erstellung, Montage, Aktualisierung und Demontage. Das Verständnis dieser Phasen ist für das Debuggen unerwarteten Verhaltens notwendig, insbesondere bei der Arbeit mit Animationen, asynchronen Operationen und Zustandsverwaltung.
Ein Element wird durch Aufruf der createElement-Methode des Widgets erstellt. Für StatelessWidget wird ein StatelessElement erstellt; für StatefulWidget wird ein StatefulElement erstellt (das auch ein State-Objekt erstellt). Für RenderObjectWidget wird das entsprechende RenderObjectElement erstellt. Die Elementerstellung erfolgt, wenn das Widget zum ersten Mal im Widget Tree erscheint.
Während der Montage wird das Element zum Element Tree hinzugefügt und erhält ein übergeordnetes Element. Für RenderObjectElement erstellt die Montage auch ein RenderObject und fügt es in den RenderObject Tree ein. Wenn das Widget ein StatefulWidget ist, wird in dieser Phase die initState-Methode des State-Objekts aufgerufen.
Wenn das Widget mit einer neuen Konfiguration neu aufgebaut wird, erhält das Element das neue Widget über die update-Methode. Das Element vergleicht den Typ des alten und neuen Widgets: Stimmen die Typen überein, aktualisiert das Element seine Konfiguration; wenn nicht, wird das Element demontiert und ein neues erstellt. Dies wird als „Widget-Wechsel" bezeichnet und ist die Ursache für Zustandsverlust beim Typwechsel.
Wenn ein Widget aus dem Widget Tree entfernt wird, wird die unmount-Methode des Elements aufgerufen. Das Element wird aus dem Element Tree entfernt, das RenderObject wird aus dem RenderObject Tree entfernt, und für StatefulWidget wird die dispose-Methode des State-Objekts aufgerufen. Nach der Demontage kann das Element wiederverwendet werden, wenn das Widget erneut an derselben Position erscheint.
Schlüssel (Key) sind ein Elementidentifikationsmechanismus, der es Flutter ermöglicht, Widgets aus dem alten und neuen Widget Tree nicht nach Position, sondern nach einer eindeutigen Kennung abzugleichen. Schlüssel sind bei der Arbeit mit dynamischen Listen, in denen sich die Reihenfolge der Elemente ändern kann, von entscheidender Bedeutung: Hinzufügen, Entfernen oder Neuanordnen von Elementen.
Ohne Schlüssel gleicht Flutter Elemente nach ihrer Position im Baum ab: Das Element an Position 0 des alten Baums wird durch das Widget an Position 0 des neuen Baums ersetzt. Wenn sich die Reihenfolge geändert hat, werden Elemente durcheinandergebracht und der Zustand kann verloren gehen oder an falsche Daten gebunden werden. Ein Schlüssel zwingt Flutter, ein Element nach Kennung statt nach Position zu suchen.
ValueKey verwendet einen einfachen Wert (Zeichenkette, Zahl) zur Identifizierung eines Elements. ObjectKey verwendet eine Objektreferenz — geeignet, wenn das Element keine stabile Zeichenkettenkennung hat. UniqueKey generiert bei jeder Erstellung eine eindeutige Kennung — wird verwendet, wenn jede Widget-Instanz eindeutig sein muss.
Column(
children: items.map((item) => TodoItem(
key: ValueKey(item.id),
title: item.title,
isDone: item.isDone,
)).toList(),
)
In diesem Beispiel stellt ValueKey mit item.id sicher, dass jeder TodoItem seinen Zustand (z. B. Fokus des Eingabefelds) behält, wenn sich die Reihenfolge der Elemente in der Liste ändert. Ohne Schlüssel würde das Element an der ersten Position den Zustand des vorherigen Elements an derselben Position erhalten.
Zustand (State) wird in Flutter nicht in Widgets, sondern in Elementen gespeichert. Wenn ein StatefulWidget neu aufgebaut wird und eine neue Widget-Instanz erstellt, behält das entsprechende StatefulElement eine Referenz auf das alte State-Objekt. Das neue Widget wird mit dem vorhandenen State verknüpft, sodass Daten zwischen Neubauten erhalten bleiben.
Beim Neubau eines Widgets erstellt Flutter eine neue Instanz von StatefulWidget, aber das entsprechende StatefulElement bleibt im Element Tree. Das Element ruft die update-Methode auf State auf und übergibt das neue Widget. Somit bleiben das State-Objekt und seine Daten erhalten. Ein Zustandsverlust tritt nur auf, wenn sich der Widget-Typ ändert, der Schlüssel ändert oder das Element aus dem Baum entfernt wird.
InheritedElement ist ein spezielles Element, das es Kind-Elementen ermöglicht, Daten von einem übergeordneten InheritedWidget ohne explizite Übergabe über Konstruktoren zu empfangen. Wenn sich InheritedWidget ändert, benachrichtigt InheritedElement alle abhängigen Elemente, die neu aufgebaut werden. Dieser Mechanismus liegt Theme, MediaQuery und Provider zugrunde.
Element Tree verbraucht Speicher und beeinflusst die Geschwindigkeit des ersten Renderings. Jedes Element belegt eine bestimmte Menge Speicher: eine Referenz auf das Widget, eine Referenz auf das übergeordnete Element, eine Liste von Kind-Elementen, einen Slot und zusätzliche Felder für RenderObjectElement. Die Optimierung des Element Tree verkürzt die Startzeit und reduziert den Speicherverbrauch.
Flutter versucht, Elemente beim Neubau wiederzuverwenden. Wenn das Widget in der neuen Konfiguration denselben Typ und Schlüssel hat, wird das Element nicht neu erstellt — es wird aktualisiert. Dies ist deutlich schneller als die Erstellung eines neuen Elements mit anschließender Montage. Wenn sich jedoch der Typ oder der Schlüssel ändert, wird das alte Element demontiert und ein neues von Grund auf erstellt.
RepaintBoundary erstellt einen separaten RenderRepaintBoundary im RenderObject Tree, der einen Teil des Baums isoliert. Auf der Ebene des Element Tree erstellt RepaintBoundary kein spezielles Element — es verwendet SingleChildRenderObjectElement. Der Unterschied zeigt sich auf der RenderObject-Ebene: Wenn sich der Inhalt von RepaintBoundary ändert, wird nur der isolierte Bereich neu gezeichnet.
| Operation | Ohne RepaintBoundary | Mit RepaintBoundary |
|---|---|---|
| Neuzeichnung | Gesamter Bildschirm | Nur isolierter Bereich |
| Zeit | ~16 ms bei 60 FPS | ~2-5 ms |
| Speicher | Minimal | + einige Kilobyte pro Ebene |
Wie die Tabelle zeigt, reduziert RepaintBoundary die Neuzeichnungszeit erheblich, indem es den sich ändernden Bereich isoliert. Auf der Ebene des Element Tree ist keine zusätzliche Konfiguration erforderlich — einfach das veränderliche Widget in RepaintBoundary einwickeln.
Häufig gestellte Fragen
Widget Tree ist eine Konfiguration, die bei jedem Neubau neu erstellt wird. Element Tree ist eine dauerhafte Struktur, die zwischen Updates bestehen bleibt und Zustand, RenderObject und Widget-Lebenszyklus verwaltet.
Ohne Element Tree müsste Flutter bei jeder Zustandsänderung den RenderObject Tree neu erstellen, was erhebliche Verzögerungen verursachen würde. Element Tree bewahrt RenderObject und State und ermöglicht so die Anwendung nur minimaler Änderungen.
Ein Element wird entfernt, wenn das entsprechende Widget aus dem Widget Tree verschwindet, oder wenn sich der Widget-Typ ändert (z. B. Column durch Row ersetzt) oder der Schlüssel ändert. Bei der Demontage wird dispose für State aufgerufen.
Schlüssel ändern den Abgleichsalgorithmus: Anstatt ein Element nach Position zu suchen, sucht Flutter ein Element nach dem Schlüsselwert. Dies ermöglicht die Beibehaltung des Zustands, wenn sich die Reihenfolge oder Anzahl der Widgets ändert.
Ja, über BuildContext, der eine Abstraktion eines Elements ist. Die Methoden findAncestorWidgetOfExactType und dependOnInheritedWidgetOfExactType arbeiten mit dem Element Tree und wandern im Elementbaum nach oben.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch