Element Tree: co to je, vztah s RenderObject a princip fungování

Autor: IT Sectr Publikováno: 2026-07-01 Doba čtení: 10 min

Element Tree je mezivrstva ve Flutter, která spojuje deklarativní Widget Tree s imperativním RenderObject Tree. Na rozdíl od widgetů, které jsou při každém rebuildu znovu vytvářeny, prvky přetrvávají mezi aktualizacemi a spravují stav, klíče a životní cyklus. Podle Flutter API Reference, 2025 je porozumění Element Tree nezbytné pro efektivní práci s klíči, optimalizaci výkonu a ladění neočekávaného chování widgetů.

Hlavní body

  • Element Tree — trvalá vrstva mezi stromy Widget a RenderObject, která přetrvává mezi přestavbami.
  • Každý widget vytváří prvek, který spravuje jeho vložení do stromu a životní cyklus.
  • StatefulElement ukládá objekt State, který zůstává přístupný i po opětovném vytvoření widgetu.
  • Klíče (Key) pracují na úrovni Element Tree a pomáhají přiřazovat widgety při přestavbě.
  • Element Tree je přímo spojen s RenderObject Tree — každý prvek může vytvořit nebo odstranit RenderObject.

Co je Element Tree ve Flutter?

Element Tree je zprostředkující hierarchie ve Flutter, která je vytvořena na základě Widget Tree a spravuje vkládání widgetů do aplikace. Každá instance prvku odpovídá jednomu widgetu ve stromu a ukládá na něj odkaz. Hlavní rozdíl mezi prvkem a widgetem je ten, že prvek si zachovává svou pozici ve stromu mezi přestavbami, zatímco widget může být při každém volání build znovu vytvořen.

Proč je Element Tree potřeba

Bez Element Tree by Flutter nemohl efektivně aktualizovat rozhraní. Pokud by každý rebuild znovu vytvářel RenderObject Tree, výkon by byl nepřijatelně nízký. Element Tree funguje jako stabilizátor: uchovává odkazy na RenderObject a State mezi aktualizacemi, což Flutter umožňuje aplikovat pouze minimální změny do vykreslovacího stromu.

Typy prvků

Flutter používá tři hlavní typy prvků: StatelessElement pro StatelessWidget, StatefulElement pro StatefulWidget a LeafRenderObjectElement, SingleChildRenderObjectElement, MultiChildRenderObjectElement pro RenderObjectWidget. Každý typ je specializovaný pro svou třídu widgetu a určuje, jak prvek interaguje s RenderObject.

Vztah Widget, Element a RenderObject v třívrstvé architektuře

Třívrstvá architektura Flutter se skládá z Widget Tree (konfigurace), Element Tree (správa) a RenderObject Tree (vykreslování). Element Tree je spojovacím článkem: čte konfiguraci z Widget a předává příkazy RenderObject. Bez Element Tree by framework nemohl efektivně synchronizovat deklarativní popis se skutečným vykreslováním.

Jak prvek spojuje widget a RenderObject

Když je prvek vložen do stromu, zkontroluje typ widgetu. Pokud je widget RenderObjectWidget, prvek vytvoří odpovídající RenderObject a přidá ho do RenderObject Tree. Pokud je widget LeafRenderObjectWidget, prvek vytvoří listový RenderObject. Pro StatelessWidget a StatefulWidget prvek jednoduše spravuje vkládání podřízených prvků.

dart
abstract class Element {
  Widget widget;
  Element? parent;
  List<Element>? children;

  void mount(Element? parent, dynamic newSlot);
  void update(Widget newWidget);
  void unmount();
}

Tento zjednodušený kód ukazuje základní strukturu Element. Každý prvek ukládá odkaz na aktuální widget, rodičovský prvek a podřízené prvky. Metody mount, update a unmount spravují životní cyklus prvku a souvisejícího RenderObject.

Životní cyklus prvku: od vytvoření po odstranění

Každý prvek ve Flutter prochází sekvencí fází životního cyklu: vytvoření, připojení, aktualizace a odpojení. Porozumění těmto fázím je nezbytné pro ladění neočekávaného chování, zejména při práci s animacemi, asynchronními operacemi a správou stavu.

Fáze 1: Vytvoření prvku

Prvek je vytvořen voláním metody createElement widgetu. Pro StatelessWidget se vytváří StatelessElement, pro StatefulWidget — StatefulElement (který také vytváří objekt State). Pro RenderObjectWidget se vytváří odpovídající RenderObjectElement. Vytvoření prvku nastává při prvním výskytu widgetu ve Widget Tree.

Fáze 2: Připojení (mount)

Při připojení je prvek přidán do Element Tree a obdrží rodičovský prvek. Pro RenderObjectElement připojení také vytváří RenderObject a vkládá ho do RenderObject Tree. Pokud je widget StatefulWidget, v této fázi je volána metoda initState objektu State.

Fáze 3: Aktualizace (update)

Když je widget přestavěn s novou konfigurací, prvek obdrží nový widget prostřednictvím metody update. Prvek porovná typ starého a nového widgetu: pokud se typy shodují, prvek aktualizuje svou konfiguraci; pokud ne — prvek je odpojen a vytvoří se nový. Tomu se říká "změna widgetu" a je to příčina ztráty stavu při změně typu.

Fáze 4: Odpojení (unmount)

Když je widget odstraněn z Widget Tree, je volána metoda unmount prvku. Prvek je odstraněn z Element Tree, RenderObject je odstraněn z RenderObject Tree a pro StatefulWidget je volána metoda dispose objektu State. Po unmount může být prvek znovu použit, pokud se widget znovu objeví na stejné pozici.

Role klíčů v Element Tree

Klíče (Key) jsou mechanismem identifikace prvků, který umožňuje Flutter přiřazovat widgety ze starého a nového Widget Tree nikoli podle pozice, ale podle jedinečného identifikátoru. Klíče jsou kriticky důležité při práci s dynamickými seznamy, kde se může pořadí prvků měnit: přidávání, odebírání nebo přesouvání prvků.

Jak klíče ovlivňují Element Tree

Bez klíče Flutter přiřazuje prvky podle jejich pozice ve stromu: prvek na pozici 0 ze starého stromu je nahrazen widgetem na pozici 0 z nového stromu. Pokud se pořadí změnilo, prvky se zamíchají a stav může být ztracen nebo připojen k nesprávným datům. Klíč nutí Flutter hledat prvek podle identifikátoru, nikoli podle pozice.

ValueKey, ObjectKey a UniqueKey

ValueKey používá jednoduchou hodnotu (řetězec, číslo) k identifikaci prvku. ObjectKey používá odkaz na objekt — vhodné, když prvek nemá stabilní řetězcový identifikátor. UniqueKey generuje jedinečný identifikátor při každém vytvoření — používá se, když každá instance widgetu musí být jedinečná.

dart
Column(
  children: items.map((item) => TodoItem(
    key: ValueKey(item.id),
    title: item.title,
    isDone: item.isDone,
  )).toList(),
)

V tomto příkladu ValueKey s item.id zaručuje, že každý TodoItem zachová svůj stav (například fokus vstupního pole) při změně pořadí prvků v seznamu. Bez klíče by prvek na první pozici získal stav předchozího prvku na stejné pozici.

Jak Element Tree spravuje stav

Stav (State) ve Flutter není uložen ve widgetech, ale v prvcích. Když je StatefulWidget přestavěn a vytváří novou instanci widgetu, odpovídající StatefulElement uchovává odkaz na starý objekt State. Nový widget se propojuje s existujícím State, což umožňuje uchovávat data mezi přestavbami.

Proč stav není ztracen při rebuildu

Při přestavbě widgetu Flutter vytváří novou instanci StatefulWidget, ale odpovídající StatefulElement zůstává v Element Tree. Prvek volá metodu update na State a předává nový widget. Tímto způsobem objekt State a jeho data zůstávají zachovány. Ztráta stavu nastává pouze při změně typu widgetu, změně klíče nebo odstranění prvku ze stromu.

InheritedWidget a Element Tree

InheritedElement je speciální prvek, který umožňuje podřízeným prvkům získávat data z rodičovského InheritedWidget bez explicitního předávání přes konstruktory. Když se InheritedWidget změní, InheritedElement informuje všechny závislé prvky, které se přestaví. Tento mechanismus je základem Theme, MediaQuery a Provider.

  • Závislost — prvek se registruje jako závislý na InheritedElement při volání dependOnInheritedWidgetOfExactType.
  • Oznámení — při změně InheritedWidget framework označí všechny závislé prvky jako vyžadující přestavbu.
  • Přestavba — závislé prvky se přestaví v následujícím snímku a aktualizují UI podle nových dat.

Vliv Element Tree na výkon

Element Tree spotřebovává paměť a ovlivňuje rychlost prvního vykreslení. Každý prvek zabírá určité množství paměti: odkaz na widget, odkaz na rodiče, seznam podřízených prvků, slot a další pole pro RenderObjectElement. Optimalizace Element Tree snižuje dobu spouštění a spotřebu paměti.

Opětovné použití prvků

Flutter se snaží znovu používat prvky při přestavbě. Pokud má widget v nové konfiguraci stejný typ a klíč, prvek není vytvořen znovu — je aktualizován. To je výrazně rychlejší než vytvoření nového prvku s následným připojením. Při změně typu nebo klíče je však starý prvek odpojen a nový je vytvořen od začátku.

RepaintBoundary a Element Tree

RepaintBoundary vytváří samostatný RenderRepaintBoundary v RenderObject Tree, který izoluje část stromu. Na úrovni Element Tree RepaintBoundary nevytváří speciální prvek — používá SingleChildRenderObjectElement. Rozdíl se projevuje na úrovni RenderObject: při změně obsahu RepaintBoundary je překreslena pouze izolovaná oblast.

OperaceBez RepaintBoundaryS RepaintBoundary
PřekresleníCelá obrazovkaPouze izolovaná oblast
Čas~16 ms při 60 FPS~2-5 ms
PaměťMinimální+ několik kilobajtů na vrstvu

Jak ukazuje tabulka, RepaintBoundary výrazně zkracuje dobu překreslení izolací měnící se oblasti. Na úrovni Element Tree to nevyžaduje další konfiguraci — stačí zabalit měnící se widget do RepaintBoundary.

Často kladené otázky

Jaký je rozdíl mezi Widget Tree a Element Tree?

Widget Tree je konfigurace, která je při každém rebuildu znovu vytvářena. Element Tree je trvalá struktura, která přetrvává mezi aktualizacemi a spravuje stav, RenderObject a životní cyklus widgetů.

Proč je Element Tree důležitý pro výkon?

Bez Element Tree by Flutter musel při každé změně stavu znovu vytvářet RenderObject Tree, což by způsobilo významná zpoždění. Element Tree uchovává RenderObject a State a umožňuje aplikovat pouze minimální změny.

Kdy je prvek odstraněn z Element Tree?

Prvek je odstraněn, když odpovídající widget zmizí z Widget Tree, nebo když se změní typ widgetu (například Column je nahrazen Row) nebo klíč. Při odpojení je volána dispose na State.

Jak klíče ovlivňují Element Tree?

Klíče mění algoritmus přiřazování: místo hledání prvku podle pozice Flutter hledá prvek podle hodnoty klíče. To umožňuje zachovat stav při změně pořadí nebo počtu widgetů.

Lze získat přímý přístup k Element Tree?

Ano, prostřednictvím BuildContext, který je abstrakcí prvku. Metody findAncestorWidgetOfExactType a dependOnInheritedWidgetOfExactType pracují s Element Tree a stoupají stromem prvků nahoru.

Shrnutí

  • Element Tree — trvalá mezivrstva mezi stromy Widget a RenderObject, která uchovává stav mezi přestavbami.
  • Každý widget vytváří prvek: StatelessElement, StatefulElement nebo RenderObjectElement, v závislosti na typu widgetu.
  • Životní cyklus prvku zahrnuje vytvoření, připojení, aktualizaci a odpojení — porozumění těmto fázím je nezbytné pro ladění.
  • Klíče (Key) pracují na úrovni Element Tree a zajišťují správné přiřazování widgetů při dynamických změnách.
  • StatefulElement ukládá objekt State, který je zachován při přestavbě widgetu, pokud se typ a klíč nemění.
  • InheritedElement informuje závislé prvky o změnách a zajišťuje reaktivní předávání dat dolů stromem.
  • Třívrstvá architektura Widget → Element → RenderObject umožňuje Flutter efektivně aktualizovat rozhraní a minimalizovat nákladné vykreslovací operace.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také