RenderObject Tree ist die dritte Ebene der Flutter-Hierarchie, verantwortlich für das tatsächliche Rendern der Benutzeroberfläche auf dem Bildschirm. Jeder Knoten dieses Baums führt die Größenberechnung (Layout) und das Zeichnen (Painting) durch und wandelt die Widget-Konfiguration in Pixel um. Im Gegensatz zum Widget Tree wird der RenderObject Tree einmal erstellt und nur bei Änderungen der Geometrie oder des Erscheinungsbilds aktualisiert. Laut Flutter API Reference, 2025 bestimmt die Effizienz des RenderObject Tree direkt die Flüssigkeit von Animationen und die Reaktionsfähigkeit der Anwendung.
Das Wichtigste
RenderObject Tree ist eine hierarchische Struktur von Render-Objekten, die als tatsächliche Darstellung der Benutzeroberfläche im Speicher dient. Jeder RenderObject kennt seine eigene Größe, Position auf dem Bildschirm und wie er sich selbst zeichnet. Im Gegensatz zu Widgets, die leichtgewichtig sind und hunderte Male pro Sekunde neu erstellt werden können, ist ein RenderObject ein schweres Objekt mit direktem Zugriff auf die Grafik-Pipeline.
Der Weg vom Widget zu Pixeln durchläuft drei Stufen: Der Widget Tree beschreibt, was auf dem Bildschirm sein soll; der Element Tree verwaltet den Lebenszyklus; der RenderObject Tree erledigt die eigentliche Arbeit. Jeder RenderObjectWidget (wie Padding, Transform, CustomPaint) erstellt ein RenderObject, das zum Renderbaum hinzugefügt wird. RenderBox ist der häufigste Typ von RenderObject, der von 99% der Standard-Widgets verwendet wird.
RenderObject ist eine abstrakte Klasse, die die Schnittstelle für Layout und Paint definiert. Sie enthält Verweise auf das Eltern-RenderObject und Kind-Objekte sowie abstrakte Methoden: performLayout, paint und hitTest. Jedes konkrete RenderObject implementiert diese Methoden entsprechend seinem Verhalten: RenderFlex verteilt Platz zwischen Kindern, RenderImage zeigt ein Bild an, RenderParagraph rendert Text.
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
In dieser vereinfachten Struktur enthält RenderObject die Flags _needsLayout und _needsPaint, die das Objekt als aktualisierungsbedürftig markieren. Wenn sich der Widget Tree ändert, markiert der Element Tree die entsprechenden RenderObjects als „schmutzig“ für Layout oder Paint, und im nächsten Frame führt Flutter nur die notwendigen Operationen durch.
Jeder RenderObject führt zwei Hauptphasen aus: Layout (Größen- und Positionsbestimmung) und Paint (Zeichnen). Diese Phasen werden in strenger Reihenfolge ausgeführt: zuerst Layout für den gesamten Baum, dann Paint. Die Paint-Phase kann übersprungen werden, wenn sich das Layout nicht geändert hat, was GPU-Ressourcen spart.
Während des Layouts übergibt Flutter Constraints von oben nach unten durch den RenderObject Tree. Jedes Elternteil legt minimale und maximale Breite und Höhe für sein Kind fest. Das Kind berechnet seine Größe innerhalb dieser Constraints und gibt sie an das Elternteil zurück. Dieser Prozess wird als „Downward Pass“ (Constraints nach unten geben) und „Upward Pass“ (Größen nach oben geben) bezeichnet.
Nach Abschluss des Layouts führt Flutter Paint durch — Zeichnen jedes RenderObject. Das Elternteil erstellt einen PaintingContext, übergibt ihn an die Kind-Objekte und gibt den Offset an. Jeder RenderObject zeichnet sich selbst auf der Canvas mit Grafikprimitiven: Rechtecke, Kreise, Text, Bilder und Transformationen. Die Canvas interagiert direkt mit Skia oder Impeller.
Flutter verwendet einen Mechanismus „schmutziger“ Knoten, um die Arbeit zu minimieren. Wenn sich nur die Größe eines RenderObject ändert, berechnet Flutter nicht das Layout des gesamten Baums neu — es markiert den geänderten Knoten und seine möglichen Vorfahren bis zum nächsten RenderBox mit fester Größe. Ähnlich wird bei einer Änderung des Erscheinungsbilds nur Paint markiert, ohne Layout zu wiederholen.
Flutter bietet mehrere Kategorien von RenderObject für verschiedene Aufgaben: RenderBox für standardmäßige rechteckige Elemente, RenderSliver für scrollbare Bereiche und benutzerdefinierte RenderObjects für nicht standardmäßiges Rendering über CustomPainter. Jeder Typ ist für seine Rolle im Renderbaum optimiert.
RenderBox ist die Basisklasse für rechteckige Oberflächenelemente. Zu seinen Untertypen gehören: RenderPadding (fügt Abstand hinzu), RenderTransform (wendet Transformationen an), RenderFlex (implementiert Row und Column), RenderStack (überlagert Elemente), RenderImage (zeigt Bilder an), RenderParagraph (rendert Text). Jeder Untertyp überschreibt performLayout und Paint für seine eigene Logik.
RenderSliver ist ein Typ von RenderObject für die Arbeit mit scrollbaren Bereichen. Im Gegensatz zu RenderBox verwendet Sliver SliverConstraints, die Viewport-Informationen enthalten. RenderSliverList und RenderSliverGrid erstellen RenderObjects nur für Elemente im sichtbaren Bereich und ermöglichen so die Handhabung von Listen mit Millionen von Einträgen.
Für nicht standardmäßige Grafiken verwenden Sie CustomPaint und CustomPainter. CustomPaint erstellt RenderCustomPaint, das die Paint-Methoden von CustomPainter aufruft. Dies ermöglicht das Zeichnen beliebiger Formen, Grafiken und Animationen mit voller Kontrolle über die Canvas. Laut Flutter-Team ist CustomPainter für komplexe Vektorgrafiken effizienter als verschachtelte Standard-Widgets.
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
canvas.drawCircle(
Offset(size.width / 2, size.height / 2),
size.width / 3,
paint,
);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
In diesem Beispiel zeichnet CirclePainter einen Kreis auf die Canvas. Die Methode shouldRepaint gibt nur dann true zurück, wenn sich die Farbe ändert, wodurch unnötiges Neuzeichnen vermieden wird. CustomPainter sollte so leichtgewichtig wie möglich sein — führen Sie alle schweren Berechnungen außerhalb der Paint-Methoden durch.
RenderObject Tree wird über den RenderObjectWidget-Mechanismus aus dem Element Tree erstellt. Jeder RenderObjectWidget (Padding, Transform, CustomPaint) erstellt ein RenderObjectElement, das wiederum das entsprechende RenderObject erstellt und verwaltet. Das Element fungiert als Vermittler: es übergibt die Konfiguration vom Widget an den RenderObject und benachrichtigt den RenderObject über Änderungen.
Wenn ein RenderObjectElement gemountet wird, ruft es die createRenderObject-Methode seines Widgets auf. Das Widget erstellt eine RenderObject-Instanz und gibt sie an das Element zurück. Das Element fügt den RenderObject in den RenderObject Tree ein, indem es die insertChildLayout-Methode des Eltern-RenderObject aufruft. Dieser Prozess erfolgt nur beim ersten Mount — bei nachfolgenden Aktualisierungen aktualisiert das Element einfach die Parameter des vorhandenen RenderObject.
Wenn sich die Konfiguration des Widgets ändert (z.B. der Padding-Wert), ruft das Element die updateRenderObject-Methode auf, die die neue Konfiguration an den vorhandenen RenderObject übergibt. Der RenderObject markiert sich selbst als „schmutzig“ für Layout oder Paint, und im nächsten Frame führt das Framework die notwendigen Aktualisierungen durch.
Wenn ein Element unmountet wird, wird die unmount-Methode aufgerufen, die den RenderObject aus dem RenderObject Tree entfernt und Ressourcen freigibt. RenderObject.remove wird aufgerufen, um sich vom Elternteil zu trennen, wonach das Objekt vom Garbage Collector erfasst werden kann. Flutter garantiert, dass kein RenderObject ohne entsprechendes Element im Baum hängt.
RepaintBoundary ist ein Widget, das eine separate Ebene zum Rendern seines Inhalts erstellt. Wenn sich der Inhalt innerhalb eines RepaintBoundary ändert, wird nur diese Ebene neu gezeichnet, während der Rest des Bildschirms unverändert bleibt. RepaintBoundary ist besonders nützlich für Animationen, Videoplayer, interaktive Diagramme und andere häufig aktualisierte Elemente.
Im Kern von RepaintBoundary steht RenderRepaintBoundary — ein spezieller RenderObject, der eine separate PictureLayer erstellt. Beim ersten Rendern zeichnet RenderRepaintBoundary Grafikbefehle in dieser Ebene auf. Bei nachfolgenden Aktualisierungen, wenn sich nur der Inhalt innerhalb des RepaintBoundary ändert, zeichnet Flutter nur diese Ebene neu, nicht den gesamten Bildschirm. Die anderen Ebenen bleiben unverändert und werden wiederverwendet.
Nicht jedes Widget benötigt RepaintBoundary. Verwenden Sie es, wenn ein Teil der Benutzeroberfläche mit hoher Frequenz (60 FPS oder höher) aktualisiert wird, während der Rest des Bildschirms statisch ist. Typische Beispiele: ein animierter Ladeindikator, Videoplayer, Spiel-Canvas, CustomPainter mit häufigem Neuzeichnen. Für statischen Text oder Schaltflächen ist RepaintBoundary überflüssig und erhöht nur den Speicherverbrauch.
| Szenario | Empfehlung | Grund |
|---|---|---|
| Animation | In RepaintBoundary einwickeln | Isoliert den häufig aktualisierten Bereich |
| Scrollbare Liste | Nicht erforderlich | ListView verwendet Ebenen automatisch |
| Statischer Text | Nicht erforderlich | Kein häufiges Neuzeichnen |
| CustomPainter | Empfohlen | Häufiges grafisches Neuzeichnen |
Die Leistung des RenderObject Tree hängt von der Anzahl der Knoten, der Tiefe des Baums und der Häufigkeit des Neuzeichnens ab. Flutter DevTools (der „Rendering“-Tab) ermöglicht die Analyse des RenderObject Tree in Echtzeit: Anzahl der Neuzeichnungen, Layout- und Paint-Zeit, Anzahl der Ebenen und ihre Größen. Regelmäßige Analysen helfen, Engpässe zu identifizieren.
Overdraw ist eine Situation, in der ein einzelner Pixel mehrmals pro Frame gezeichnet wird. Wenn beispielsweise ein halbtransparentes Widget ein anderes überlappt, zeichnet die GPU beide Ebenen. Verwenden Sie undurchsichtige Flags (Container mit color statt decoration) für nicht transparente Elemente, damit Flutter unsichtbare Ebenen überspringen kann. Laut Flutter-Team kann die Reduzierung von Overdraw die Paint-Zeit um bis zu 30% senken.
Jeder RepaintBoundary und einige Widgets (Opacity, ClipRRect, Transform) erstellen eine separate Ebene (PictureLayer). Zu viele Ebenen erhöhen die Kompositionszeit. Verwenden Sie Gruppierung: statt mehrerer Opacity-Widgets auf einzelnen Elementen wenden Sie eine einzelne Opacity auf den Container an. Statt ClipRRect auf jedem Element verwenden Sie ClipRRect auf dem gemeinsamen Container.
Wenn ein Widget als const deklariert ist, weiß Flutter, dass sich seine Konfiguration nicht ändern wird, und kann das entsprechende RenderObject ohne Neuerstellung wiederverwenden. Const-Konstruktoren reduzieren die Belastung des Garbage Collectors und beschleunigen den ersten Frame. Verwenden Sie const für Widgets mit festen Parametern: Symbole, Titel, dekorative Elemente.
const Text("Title", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
Häufig gestellte Fragen
Widget Tree ist eine leichte Oberflächenkonfiguration, die bei jedem Neubau neu erstellt wird. RenderObject Tree ist ein schwerer Baum von Render-Objekten, der bestehen bleibt und nur bei Änderungen der Geometrie oder des Erscheinungsbilds aktualisiert wird.
Verwenden Sie Flutter DevTools — den „Rendering“-Tab. Sie sehen Renderebenen, Layout- und Paint-Zeiten sowie detaillierte Informationen zu jedem RenderObject: Größen, Constraints und Dirty-Flags.
Dirty ist ein RenderObject, das als aktualisierungsbedürftig markiert ist. Das Flag _needsLayout oder _needsPaint wird gesetzt, wenn sich die Konfiguration ändert, und Flutter führt im nächsten Frame Layout oder Paint für diesen Knoten durch.
Ja, erstellen Sie eine Unterklasse von RenderBox und überschreiben Sie die Methoden performLayout und paint. Verwenden Sie RenderObjectWidget, um einen benutzerdefinierten RenderObject in den Widget Tree einzubetten. Dies ist eine fortgeschrittene Technik für nicht standardmäßiges Rendering.
RepaintBoundary erstellt RenderRepaintBoundary, das einen Teil des RenderObject Tree in eine separate Ebene isoliert. Wenn sich der Inhalt ändert, wird nur diese Ebene neu gezeichnet, der Rest des Baums bleibt unverändert.
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