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 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.
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.
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.
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 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.
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.
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.
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í.
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.
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.
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 „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.
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 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.
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.
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.
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.
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.
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.
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.
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 %.
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 „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.
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
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.
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.
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.
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.
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í
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í.
Přečtěte si také