State — centrální objekt pro správu dat ve Flutter, spojený se StatefulWidget a zodpovědný za ukládání měnitelných informací a budování rozhraní. Podle oficiální dokumentace Flutter (Flutter.dev, 2026) State existuje po celý životní cyklus widgetu a přežívá jeho přestavby, čímž zajišťuje konzistenci dat mezi aktualizacemi UI. Na rozdíl od samotného widgetu může State měnit svá pole a iniciovat přestavbu pomocí volání setState.
Hlavní body
State — je objekt v architektuře Flutter, který ukládá měnitelná data StatefulWidget a určuje, jak se tato data zobrazují v rozhraní. Každý StatefulWidget při vložení do stromu vytváří právě jeden objekt State prostřednictvím metody createState. State existuje nezávisle na widgetu: pokud rodič přestaví StatefulWidget s novými parametry, State zůstává stejný a přijímá aktualizovaný widget pomocí vlastnosti widget.
Podle Flutter Architectural Overview (Google, 2026) je oddělení Widget a State vědomé architektonické rozhodnutí, které frameworku umožňuje znovu používat prvky stromu. Widget (lehký popis) může být vytvořen a zničen několikrát, ale State (těžký objekt s daty) zůstává v paměti, dokud je prvek ve stromu. To zabraňuje ztrátě dat při častých přestavbách rodičovských widgetů.
State implementuje rozhraní StatefulWidget prostřednictvím generika: class _MyState extends State<MyWidget>. Generikum spojuje State s konkrétním typem StatefulWidget a poskytuje typově bezpečný přístup k jeho polím prostřednictvím vlastnosti widget.
Objekt State je uložen v StatefulElement — mezivrstvě mezi Widget a RenderObject. StatefulElement vytváří State pomocí createState, uchovává odkaz na něj a předává State jako vlastníka. Element je zničen pouze tehdy, když je widget odstraněn ze stromu — do té doby State žije v paměti.
Životní cyklus State je deterministický a skládá se z přísné posloupnosti volání. Porozumění této posloupnosti je základem správné práce se zdroji a prevence úniků paměti.
initState je volán jako první při vytváření State. V této metodě se inicializují ovladače, předplatné datových toků, časovače a počáteční hodnoty polí. Volání super.initState() na prvním řádku je povinné. Ve fázi initState není strom widgetů ještě zcela připojen, takže metody jako MediaQuery.of(context) mohou pracovat nesprávně.
didChangeDependencies je volán po initState a při každé změně závislostí InheritedWidget. Právě zde, nikoli v initState, by se měly volat MediaQuery.of(context) nebo Theme.of(context), protože v této chvíli je strom již připojen. Tato metoda je také volána, pokud je widget přesunut do jiného kontextu, kde InheritedWidget poskytuje jiné hodnoty.
build — hlavní metoda State, která vrací strom widgetů. Volána po initState, po didChangeDependencies a po každém setState. Metoda build by neměla mít vedlejší účinky — pouze popisuje rozhraní na základě aktuálních hodnot polí State.
didUpdateWidget je volán, když rodič přestaví StatefulWidget s novými parametry. State získá přístup ke starému widgetu prostřednictvím oldWidget a může jej porovnat s novým. Pokud se parametry změnily, lze aktualizovat stav, načíst nová data nebo restartovat animaci.
dispose — závěrečná metoda, ve které se uvolňují všechny zdroje: ovladače, předplatné, časovače. Po dispose je State označen jako mrtvý: mounted vrací false, volání setState vyhodí výjimku. Volání super.dispose() na posledním řádku metody je povinné.
| Metoda | Kdy je volána | Povinné super |
|---|---|---|
| initState | Při vytváření State | Ano, na prvním řádku |
| didChangeDependencies | Po initState a při změně InheritedWidget | Ano |
| build | Po initState, didChangeDependencies, setState | Ne |
| didUpdateWidget | Při novém widgetu od rodiče | Ano |
| setState | Na volání vývojáře | Ne |
| dispose | Při odstranění ze stromu | Ano, na posledním řádku |
Mechanismus fungování State je založen na třech klíčových principech: asociaci s Element, reaktivitě prostřednictvím setState a přístupu k rodiči pomocí vlastnosti widget. Když Flutter buduje strom prvků a narazí na StatefulElement, zavolá createState přidruženého widgetu. Vytvořený State je uložen v prvku a existuje, dokud není prvek odstraněn.
Při volání setState se State označí jako špinavý (dirty) a naplánuje přestavbu na další snímek. Důležité: setState nevolá build okamžitě — pouze registruje potřebu přestavby. Flutter shromáždí všechny špinavé prvky v aktuálním snímku a přestaví je dávkově, což optimalizuje výkon. Po volání build se State vrátí do čistého (clean) stavu.
Vlastnost widget umožňuje State číst parametry předané konstruktoru StatefulWidget. Protože je StatefulWidget neměnný (jako StatelessWidget), jeho pole se nemění — při změně parametrů vytvoří rodič nový widget a State jej obdrží prostřednictvím didUpdateWidget. To zaručuje, že State vždy pracuje s aktuálními daty rodiče.
Základní příklad State s polem měnícím se podle časovače. Demonstruje initState, setState a dispose:
class _TimerWidgetState extends State<TimerWidget> {
int _seconds = 0;
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(
const Duration(seconds: 1),
(_) => setState(() => _seconds++),
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text('$_seconds sekund uplynulo');
}
}
Příklad použití vlastnosti widget pro přístup k parametrům rodiče a reakci na jejich změny prostřednictvím didUpdateWidget:
class _GreetingState extends State<GreetingWidget> {
String _displayName = '';
@override
void initState() {
super.initState();
_displayName = _formatName(widget.name);
}
@override
void didUpdateWidget(GreetingWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.name != oldWidget.name) {
setState(() {
_displayName = _formatName(widget.name);
});
}
}
String _formatName(String name) => name.trim().isEmpty ? 'Guest' : name;
@override
Widget build(BuildContext context) {
return Text('Ahoj, $_displayName!');
}
}
Ve druhém příkladu State sleduje změnu vstupního parametru name a přeformátuje zobrazení pouze při skutečné změně. Bez kontroly widget.name != oldWidget.name by se metoda volala při každé přestavbě rodiče, i když se název nezměnil — to je zbytečná práce pro framework.
State a StatefulWidget jsou dvě různé třídy v architektuře Flutter s různými rolemi. StatefulWidget je lehký neměnný obal, který popisuje konfiguraci widgetu a vytváří State. State je těžký objekt, který ukládá měnitelná data, spravuje předplatné a buduje UI. Toto oddělení umožňuje Flutter ničit a vytvářet widgety bez ztráty stavu.
Všechna pole StatefulWidget musí být final a nastavena v konstruktoru — po vytvoření se nemění. State naproti tomu může svá pole kdykoli měnit, ale všechny změny musí předcházet volání setState, aby se Flutter dozvěděl o potřebě přestavby. To je klíčový rozdíl: StatefulWidget je „co zobrazit“, State — „jak zobrazit a jaká data použít“.
Podle analýzy zdrojového kódu Flutter (Flutter SDK, 2026) obsahuje StatefulWidget pouze jedno povinné pole — createState, zatímco State má přístup k BuildContext, může se předplácet na toky, spravovat animace a ovladače. Doporučuje se udržovat StatefulWidget co nejjednodušší a přenést veškerou logiku do State.
Oddělení Widget a State je architektonické rozhodnutí zajišťující neměmost konfigurace. Pokud by StatefulWidget sám ukládal stav, při každé přestavbě rodiče by se stav ztrácel. Vydělením stavu do samostatného objektu Flutter zaručuje, že data přežijí přestavby a widgety zůstanou lehké a srovnatelné.
Objekt State je izolovaný — nemá přímý přístup k State jiných widgetů. Pro výměnu dat mezi widgety se používá InheritedWidget nebo externí nástroje pro správu stavu: Provider, Riverpod, Bloc, Redux. Každý přístup řeší úkol svým způsobem: InheritedWidget pracuje prostřednictvím stromu widgetů, Provider prostřednictvím DI kontejneru, Bloc prostřednictvím toků událostí.
Výběr nástroje závisí na měřítku projektu. Pro malou aplikaci stačí InheritedWidget a místní State. Pro střední a velký projekt se doporučuje Riverpod nebo Bloc — poskytují testovatelnost, předvídatelnost a oddělení logiky od UI. State se přitom používá pouze pro místní data widgetu (fokus, skrol, animace).
Podle Flutter Community Survey 2025 (Flutter Foundation, prosinec 2025) je Riverpod nejoblíbenějším řešením pro správu stavu v nových projektech (38%), následuje Bloc (31%) a Provider (22%). Všechny tři nástroje jsou kompatibilní se State a nevyžadují opuštění standardního životního cyklu.
První chyba — zapomenout zkontrolovat mounted před setState v asynchronním callbacku. Když je widget odstraněn ze stromu (např. uživatel opustil obrazovku), ale asynchronní operace (HTTP požadavek) stále běží, po jejím dokončení je State již mrtvý. Volání setState v mrtvém State vyhodí výjimku. Kontrola if (mounted) setState(...) řeší problém.
Druhá chyba — inicializace závislostí InheritedWidget v initState místo v didChangeDependencies. V initState kontext ještě není připojen, takže MediaQuery.of(context) vyhodí výjimku. Všechny závislosti InheritedWidget by měly být konfigurovány v didChangeDependencies nebo v build.
Třetí chyba — mutace polí bez volání setState. Pokud vývojář změní pole State bez setState, Flutter se o změně nedozví a UI se neaktualizuje. Například: _list.add(item) bez následného setState((){}) změní seznam, ale obrazovka zůstane stejná.
Bezpečnostní vzor pro asynchronní operace ve State:
Future<void> _fetchData() async {
final data = await ApiService.fetch();
if (mounted) {
setState(() => _data = data);
}
}
Kontrola mounted zaručuje, že setState je volán pouze pro živý State, čímž se zabrání výjimce „setState called after dispose“.
Často kladené otázky
StatefulWidget je neměnná konfigurace widgetu, zatímco State je měnitelný objekt ukládající data a řídící životní cyklus. Widget může být znovu vytvořen, State — ne. StatefulWidget vytváří State pomocí createState.
Přesně jeden. Metoda createState je volána jednou při prvním vložení StatefulWidget do stromu. I když rodič opakovaně přestavuje, objekt State zůstává stejný, dokud se nezmění typ nebo Key widgetu.
mounted je booleovský příznak ukazující, zda je State ve stromu widgetů. Po volání dispose se mounted stane false. Používá se ke kontrole před setState v asynchronních callback k zabránění výjimce.
Ne. State je vždy vázán na konkrétní StatefulWidget prostřednictvím generika: State<T extends StatefulWidget>. Vytvoření State přímo, bez asociace s widgetem, je architektonicky nemožné.
Vyhodí se výjimka: „setState called after dispose“. Po volání dispose je State považován za mrtvý a veškeré pokusy o přestavbu UI prostřednictvím setState jsou zakázány. Řešení — kontrolujte mounted před každým setState.
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é