Widget Tree: co to je, struktura a role ve stromu widgetů

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

Widget Tree „je hierarchická struktura widgetů ve Flutteru, která určuje kompozici uživatelského rozhraní. Každý prvek rozhraní, od tlačítka po celou obrazovku, je reprezentován samostatným widgetem vnořeným do nadřazeného kontejneru. Flutter aktualizuje Widget Tree při každé změně stavu „ framework porovnává nový a starý strom a aplikuje minimální změny. Podle údajů Flutter Team, 2025, efektivní struktura stromu přímo ovlivňuje plynulost animací a rychlost odezvy rozhraní.

Hlavní body

  • Widget Tree „je hierarchie, ve které je každý Flutter widget uzlem a vnoření odráží kompozici UI.
  • Každý rebuild znovu vytváří konfiguraci widgetů, ale nemusí nutně překreslovat obrazovku „ za to odpovídají Element a RenderObject.
  • StatelessWidget nemá vnitřní stav, zatímco StatefulWidget ukládá data ovlivňující rebuild stromu.
  • Klíče (Key) pomáhají Flutteru identifikovat widgety při přestavbě a zabraňují ztrátě stavu.
  • Hloubka stromu ovlivňuje výkon „ nadměrné vnoření může zpomalit fázi layoutu renderování.

Co je Widget Tree ve Flutteru?

Widget Tree „je deklarativní popis uživatelského rozhraní ve Flutteru, vytvořený jako strom vnořených widgetů. Každý widget definuje část UI: svou konfiguraci, parametry zobrazení a chování při interakci. Vývojář popisuje, jak má rozhraní vypadat v aktuálním stavu aplikace, a Flutter je zodpovědný za převod tohoto popisu na pixely na obrazovce.

Deklarativní přístup Flutteru

Na rozdíl od imperativních frameworků, kde vývojář přímo manipuluje s prvky rozhraní, Flutter používá deklarativní přístup. Při změně stavu aplikace se vytvoří nový Widget Tree a framework vypočítá rozdíl mezi starým a novým stromem. To minimalizuje počet operací kreslení a činí kód předvídatelnějším.

dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Widget Tree")),
        body: Center(
          child: Column(
            children: [
              Text("Ahoj, Flutter"),
              ElevatedButton(
                onPressed: () {},
                child: Text("Stiskni mě"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

V tomto příkladu se Widget Tree skládá z MaterialApp, Scaffold, AppBar, Center, Column, Text a ElevatedButton. Každý z těchto widgetů je uzlem stromu. Když se stav aplikace změní, Flutter znovu zavolá metodu build a porovná výsledek s předchozím stromem.

Struktura Widget Tree: kořenové a podřízené widgety

Widget Tree začíná kořenovým widgetem, který je předán metodě runApp. Kořenový widget je obvykle MaterialApp, CupertinoApp nebo WidgetsApp „ nastavuje globální nastavení aplikace. Od kořene se strom větví do podřízených widgetů, z nichž každý může obsahovat vlastní potomky.

Widgety s jedním a více potomky

Widgety ve Flutteru se dělí na single-child (přijímají jednoho potomka přes parametr child) a multi-child (přijímají seznam potomků přes children). Příklady single-child: Center, Padding, SizedBox, Container. Multi-child: Column, Row, Stack, ListView, GridView. Tento rozdíl ovlivňuje strukturu Widget Tree: multi-child widgety vytvářejí širší stromy, zatímco single-child vytvářejí hlubší stromy.

Role BuildContext ve stromu

BuildContext „je umístění widgetu ve Widget Tree. Každý widget má svůj BuildContext, který je předán metodě build a používá se pro přístup k nadřazeným widgetům, tématu, MediaQuery a dalším InheritedWidget. BuildContext je mostem mezi widgetem a jeho prvkem v Element Tree.

dart
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final mediaQuery = MediaQuery.of(context);
    return Container(
      color: theme.colorScheme.primary,
      child: Text(
        "Šířka obrazovky: ${mediaQuery.size.width}"
      ),
    );
  }
}

V tomto příkladu je BuildContext použit k získání tématu a rozměrů obrazovky. Flutter stoupá ve Widget Tree k nejbližšímu Theme a MediaQuery, které jsou InheritedWidget. To ukazuje, jak kontext spojuje widget s jeho pozicí v hierarchii.

Jak Flutter buduje Widget Tree při spuštění?

Při spuštění Flutter aplikace je volána funkce runApp, která přijímá kořenový widget a zahajuje budování Widget Tree. Proces zahrnuje tři fáze: vytvoření konfigurace widgetů, formování Element Tree a vytvoření RenderObject Tree pro skutečné kreslení.

Fáze 1: Vytvoření kořenového widgetu

Funkce runApp vytváří kořenový prvek prostřednictvím WidgetsFlutterBinding, který spojuje framework s grafickým motorem. Kořenový widget je umístěn do stromu a Flutter volá metodu build pro jeho naplnění podřízenými widgety. Každé volání build generuje nový podgraf Widget Tree.

Fáze 2: Počáteční layout

Po vytvoření Widget Tree Flutter provádí počáteční layout „ výpočet rozměrů a pozic všech widgetů. Tento proces začíná od kořene a šíří se dolů stromem. Každý widget obdrží omezení od rodiče a vrátí vypočítanou velikost. Pokud se velikosti neshodují, Flutter generuje chybu layoutu.

Fáze 3: Kreslení na obrazovku

Po dokončení layoutu Flutter zahájí kreslení každého widgetu. RenderObject převádí popis rozhraní na grafické příkazy, které jsou prováděny GPU přes Skia nebo Impeller. Celý proces „ od Widget Tree po pixely „ se opakuje při každé aktualizaci stavu s frekvencí až 120 snímků za sekundu.

StatelessWidget a StatefulWidget v hierarchii stromu

StatelessWidget „je widget, který nemá vnitřní měnitelný stav. Jeho vzhled je zcela určen vstupními parametry předanými přes konstruktor. Pokud se parametry nezměnily, StatelessWidget se nepřestavuje. To ho činí lehkým z hlediska výkonu.

Kdy použít StatelessWidget

Použijte StatelessWidget pro statické prvky rozhraní: ikony, textové popisky, dekorativní oddělovače a jednoduchá tlačítka bez vnitřní logiky. Podle Flutter dokumentace může být přibližně 70 % widgetů v typické aplikaci StatelessWidget, což snižuje zatížení garbage collectoru a zrychluje rebuild.

StatefulWidget a správa stavu

StatefulWidget vytváří objekt State, který je zachován mezi přestavbami widgetu. Když se stav změní (prostřednictvím volání setState), Flutter označí widget jako „špinavý“ a při příštím snímku ho přestaví. StatefulWidget umožňuje implementaci interaktivních prvků: vstupní pole, animace, časovače a dynamické seznamy.

dart
class CounterWidget extends StatefulWidget {
  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text("Počet: $_count"),
        ElevatedButton(
          onPressed: () {
            setState(() => _count++);
          },
          child: Text("Zvýšit"),
        ),
      ],
    );
  }
}

V tomto příkladu StatefulWidget používá setState ke změně počítadla. Když je stav aktualizován, Flutter přestaví pouze změněnou část Widget Tree „ widget CounterWidget a jeho potomky. Nadřazené widgety se nepřestavují, což je klíčová výhoda deklarativního modelu Flutteru.

Jak Widget Tree souvisí s Element Tree

Widget Tree je konfigurační vrstva a Element Tree je mezičlánek mezi widgety a skutečným kreslením. Každý widget ve Widget Tree vytváří prvek v Element Tree, který ukládá odkaz na widget a spravuje životní cyklus. Tato architektura umožňuje Flutteru efektivně zpracovávat změny.

Vytvoření prvku z widgetu

Když Flutter poprvé narazí na widget, zavolá metodu createElement, která vytvoří odpovídající prvek. Pro StatelessWidget se vytváří StatelessElement, pro StatefulWidget StatefulElement, který také vytváří objekt State. Prvek je zachován mezi cykly rebuild, i když je widget znovu vytvořen.

Mechanismus Keys v Element Tree

Key „je identifikátor, který pomáhá Flutteru přiřadit widgety ze starého a nového Widget Tree. Pokud má widget Key, Flutter ho použije k nalezení odpovídajícího prvku, nikoli pozici ve stromu. Klíče jsou nezbytné při práci s dynamickými seznamy, kde se pořadí prvků může měnit.

dart
ListView(
  children: items.map((item) => ListItem(
    key: ValueKey(item.id),
    data: item,
  )).toList(),
)

Bez Key Flutter přiřazuje prvky podle pozice, což může při změně pořadí vést k nesprávnému zachování stavu. ValueKey s jedinečným identifikátorem zaručuje, že každý prvek zachová svůj stav bez ohledu na pozici v seznamu.

Vliv Widget Tree na výkon

Struktura Widget Tree přímo ovlivňuje výkon Flutter aplikace. Hluboké stromy s velkým počtem vnořených widgetů vyžadují více času pro fázi layoutu a zvyšují spotřebu paměti. Flutter DevTools poskytuje nástroje pro analýzu Widget Tree a identifikaci úzkých míst.

Nadměrné vnoření

Každá úroveň vnoření přidává další výpočty při layoutu a paintu. Místo hlubokého řetězového vnoření používejte plošší struktury. Například Row s Expanded může nahradit několik vnořených Containerů s Align. Podle Flutter Team může optimalizace stromu snížit čas layoutu až o 40 %.

  • Layout „každý rodič předává omezení podřízeným widgetům a získává velikosti zpět, což při hlubokém vnoření vytváří řetězec výpočtů.
  • Paint „každý widget může vytvořit samostatnou vrstvu pro kreslení a nadměrné vnoření zvyšuje počet vrstev.
  • Memory „každý prvek v Element Tree zabírá paměť a nadbytečné widgety zvyšují spotřebu zdrojů.

Nástroje pro analýzu Widget Tree

Flutter DevTools poskytuje widget “Widget Inspector”, který zobrazuje aktuální Widget Tree v reálném čase. Vývojář může vybrat libovolný widget na obrazovce a vidět jeho místo ve stromu, parametry a omezení layoutu. To pomáhá identifikovat neočekávané vnoření, zbytečné rebuildy a problémy s velikostí.

RepaintBoundary pro optimalizaci

RepaintBoundary „je widget, který izoluje část Widget Tree pro samostatné kreslení. Pokud se obsah RepaintBoundary změní, překreslí se pouze jeho oblast, ne celá obrazovka. Použijte RepaintBoundary pro animace, seznamy a další často aktualizované prvky.

dart
RepaintBoundary(
  child: CustomPaint(
    painter: MyPainter(),
    child: SizedBox(
      width: 200,
      height: 200,
    ),
  ),
)

V tomto příkladu RepaintBoundary izoluje CustomPaint do samostatné oblasti kreslení. Při aktualizaci animace uvnitř této oblasti se překreslí pouze widget CustomPaint, zbytek obrazovky zůstává nezměněn. To je užitečné zejména ve složitých rozhraních s mnoha animovanými prvky.

Často kladené otázky

Čím se Widget Tree liší od Element Tree?

Widget Tree „je deklarativní popis rozhraní, který je znovu vytvářen při každém rebuildu. Element Tree je zachován mezi aktualizacemi a spravuje životní cyklus, stav a přiřazování widgetů ke skutečným RenderObject.

Kolik widgetů může být ve Widget Tree?

Neexistuje omezení počtu widgetů, ale v praxi může strom s tisíci widgety zpomalit fázi layoutu. Flutter je optimalizován pro stromy do několika tisíc uzlů; při větším počtu se doporučuje virtualizace přes ListView.builder.

Jak zobrazit Widget Tree v debuggeru?

Použijte Flutter DevTools „ kartu “Widget Inspector”. Spusťte aplikaci v režimu debug, otevřete DevTools v prohlížeči a vyberte libovolný widget na obrazovce pro zobrazení jeho místa ve Widget Tree.

Co je rebuild Widget Tree?

Rebuild „je proces opětovného vytvoření konfigurace widgetů při změně stavu. Flutter znovu zavolá metodu build pro změněné widgety, porovná nový Widget Tree s předchozím a aplikuje minimální změny na Element Tree.

Jak optimalizovat Widget Tree?

Snižte hloubku vnoření, používejte const widgety pro statické prvky, aplikujte RepaintBoundary pro izolaci animací a vyhněte se zbytečným StatefulWidget tam, kde stačí StatelessWidget.

Shrnutí

  • Widget Tree „hierarchický deklarativní popis UI ve Flutteru, kde každý uzel je widget s konfigurací a parametry.
  • Flutter buduje Widget Tree při spuštění přes runApp, provádějící tři fáze: vytvoření kořenového widgetu, layout a kreslení.
  • StatelessWidget nemá stav a přestavuje se pouze při změně vstupních parametrů, StatefulWidget používá setState pro správu dynamických dat.
  • Element Tree je zachován mezi přestavbami a spojuje Widget Tree s RenderObject Tree prostřednictvím prvků.
  • Klíče (Key) zajišťují správné přiřazení widgetů při přestavbě, zejména v dynamických seznamech.
  • Hloubka stromu ovlivňuje výkon „ nadměrné vnoření zvyšuje čas layoutu a spotřebu paměti.
  • RepaintBoundary izoluje část Widget Tree pro lokální překreslení a snižuje zátěž GPU při animacích.

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é