BuildContext — fundamentální objekt Flutteru, který představuje pozici konkrétního widgetu ve stromu elementů a poskytuje přístup k jeho okolí. Podle oficiální dokumentace Flutteru (Flutter.dev, 2026) je BuildContext mostem mezi widgetem a frameworkem: skrze něj widget získává motiv (Theme), media dotazy (MediaQuery), lokalizaci (Localizations) a data z InheritedWidget. Každý widget má svůj vlastní BuildContext, předávaný do metody build jako první argument.
Hlavní body
BuildContext — je rozhraní implementované třídou Element, které poskytuje widgetu informace o jeho umístění v hierarchii UI. Každá instance BuildContext je jedinečná pro konkrétní pozici ve stromu a nelze ji přesunout na jiné místo. Pokud widget změní svého rodiče (například je přesunut do jiného kontejneru), obdrží nový BuildContext.
Hlavním účelem BuildContext je přístup k InheritedWidget. Prostřednictvím kontextu widget najde nejbližší instanci Theme, MediaQuery, Navigator nebo Directionality, pohybem nahoru stromem. Tento mechanismus je základem celého systému motivů, navigace a adaptivního rozvržení ve Flutteru. Bez BuildContext žádný widget nemůže tato data získat.
Podle Flutter architectural docs (Google, 2026) se BuildContext také používá k vyhledání objektu RenderObject přidruženého k widgetu, pro měření rozměrů a pozicování. Metody jako findRenderObject() a size jsou dostupné právě přes kontext. Kontext také poskytuje přístup k lokalizaci přes Localizations.of(context).
Důležité architektonické pochopení: BuildContext je rozhraní, které implementuje Element, nikoli Widget. Element je „lepidlo” mezi Widgetem (konfigurací) a RenderObjectem (skutečným zobrazením). Když se v dokumentaci říká „kontext widgetu” — mluví se o elementu, který tento widget spravuje. Metoda build získává právě takový kontext — kontext vytvářeného widgetu, nikoli vrácených podřízených widgetů.
Mechanismus fungování BuildContext je založen na procházení stromu elementů zdola nahoru. Když widget zavolá Theme.of(context), kontext zahájí vyhledávání od aktuálního elementu a pohybuje se nahoru ke kořeni, přičemž kontroluje každý element na přítomnost InheritedWidget s typem Theme. První nalezený InheritedWidget je vrácen — to zaručuje, že widget obdrží motiv z nejbližší definice.
Každý BuildContext uchovává odkaz na rodičovský kontext (parent) a na podřízené kontexty. Toto je obousměrné spojení umožňující pohyb ve stromu jak nahoru (k rodičům), tak dolů (k potomkům). Ve Flutteru se pro vyhledávání InheritedWidget používá pouze pohyb nahoru — widget může získat data pouze od předků, ne od potomků. Toto je fundamentální architektonické omezení.
Podle zdrojového kódu Flutteru (Flutter SDK, 2026) BuildContext obsahuje metody: visitAncestorElements, visitChildElements, findAncestorWidgetOfExactType, dependOnInheritedWidgetOfExactType a getRenderObject. Poslední dvě jsou nejpoužívanější: dependOnInheritedWidgetOfExactType nejen najde InheritedWidget, ale také se přihlásí k odběru jeho změn (widget bude znovu postaven při změně InheritedWidget).
dependOnInheritedWidgetOfExactType — klíčová metoda BuildContext zajišťující reaktivitu. Když widget zavolá Theme.of(context), nejenže obdrží motiv — přihlásí se k odběru jeho změn. Pokud se Theme změní (například při přepnutí tmavého/světlého motivu), všechny přihlášené widgety se automaticky znovu postaví. Toto je mechanismus reaktivity ve Flutteru.
BuildContext je rozhraní a Element — jeho implementace. Ve Flutter kódu pracujete vždy přes rozhraní BuildContext, aniž byste znali konkrétní typ elementu (StatelessElement, StatefulElement, ProxyElement atd.). To je záměrné: vývojář nepotřebuje znát detaily implementace elementu — rozhraní stačí pro přístup k okolí.
Různé typy elementů implementují BuildContext odlišně: StatelessElement pouze předává volání build, StatefulElement spravuje State, a InheritedElement sleduje odběry přes dependOnInheritedWidgetOfExactType. Z pohledu vývojáře jsou však všechny BuildContext s jednotným API.
| Aspekt | BuildContext | Element |
|---|---|---|
| Typ | Rozhraní (abstract class) | Třída implementace |
| Použití | Vývojářem v build | Vnitřní mechanismus Flutteru |
| Metody vyhledávání | of(), findAncestor...() | mount, update, unmount |
| Veřejnost | Veřejné API | package-internal |
| Spojení s widgetem | Přes pole widget | Vlastní widget a state |
Základní použití BuildContext pro přístup k motivu a media dotazům:
class ThemedText extends StatelessWidget {
const ThemedText({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final media = MediaQuery.of(context);
return Container(
padding: EdgeInsets.all(media.size.width * 0.02),
child: Text(
'Styled Text',
style: theme.textTheme.headlineMedium,
),
);
}
}
Příklad s navigací přes BuildContext. Navigator.of(context) používá kontext k vyhledání nejbližšího Navigatoru nahoru stromem:
class _NavigateButtonState extends State<NavigateButton> {
void _navigate() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const DetailsScreen(),
),
);
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _navigate,
child: const Text('Go to Details'),
);
}
}
Příklad zjištění velikosti widgetu přes BuildContext. Metoda findRenderObject() vrací RenderObject, ze kterého lze získat velikost:
void _printSize(BuildContext context) {
final renderBox = context.findRenderObject() as RenderBox?;
if (renderBox != null) {
print('Widget size: ${renderBox.size}');
}
}
Důležité: findRenderObject() vrací null, pokud widget ještě není připojen nebo již byl odpojen. Před použitím vždy zkontrolujte výsledek na null. Volání této metody uvnitř build před dokončením konstrukce může také vrátit null.
InheritedWidget — speciální widget, který efektivně šíří data dolů stromem přes BuildContext. Když podřízený widget zavolá MyInheritedWidget.of(context), BuildContext stoupá stromem, najde nejbližší InheritedWidget odpovídajícího typu a vrátí jeho data. Přitom se kontext přihlásí k odběru změn: pokud se InheritedWidget změní, všechny přihlášené widgety se automaticky znovu postaví.
Kombinace BuildContext + InheritedWidget nahrazuje globální proměnné a prop-drilling (předávání dat řetězcem konstruktorů). Místo předávání motivu přes 10 úrovní widgetů, každý widget jej může získat přímo přes Theme.of(context). To činí kód čistším a snižuje počet předávaných parametrů.
Podle Flutter Team (Google, duben 2026) je InheritedWidget natolik efektivní mechanismus, že na něm jsou postavena všechna oficiální řešení pro správu stavu: Provider obaluje InheritedWidget, Riverpod jej používá jako jednu z vrstev, a samotný Flutter SDK (Theme, MediaQuery, Navigator, Localizations) je zcela založen na této architektuře.
Vytvoření vlastního InheritedWidget umožňuje šíření dat bez externích závislostí. Třída rozšiřuje InheritedWidget a poskytuje statickou metodu of(BuildContext context). To je minimalistická alternativa k Provideru pro jednoduché scénáře:
class AppConfig extends InheritedWidget {
final String apiUrl;
final bool useDarkMode;
const AppConfig({
super.key,
required this.apiUrl,
required this.useDarkMode,
required super.child,
});
static AppConfig of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<AppConfig>()!;
}
@override
bool updateShouldNotify(AppConfig oldWidget) {
return apiUrl != oldWidget.apiUrl || useDarkMode != oldWidget.useDarkMode;
}
}
Nyní může jakýkoli widget níže ve stromu přistupovat ke konfiguraci: final config = AppConfig.of(context);. Pokud se konfigurace změní, všechny přihlášené widgety budou automaticky znovu postaveny.
První typická chyba — uchovávání BuildContext po dispose nebo použití v asynchronním callbacku bez kontroly mounted. BuildContext je vázán na element a element může být zničen (při odstranění widgetu ze stromu). Použití kontextu po zničení elementu vede k výjimce. Řešení — používejte context.mounted (dostupné v novějších verzích Flutteru) nebo kontrolujte mounted v State.
Druhá chyba — volání Theme.of(context) v initState. Ve fázi initState kontext ještě není plně připojen ve stromu. Vyhledávání InheritedWidget v initState může vrátit null nebo vyvolat výjimku. Všechna volání of(context) by měla být prováděna v build nebo didChangeDependencies, kde je kontext zaručeně ve stromu.
Třetí chyba — použití BuildContext z jednoho widgetu k manipulaci s jiným widgetem. BuildContext není určen pro mezividgetovou interakci mimo hierarchii „rodič-potomek”. Pokud potřebujete spravovat stav jiného widgetu — používejte callbacky, controllery nebo nástroje pro správu stavu.
Čtvrtá chyba — předání BuildContext asynchronní funkci, která přežije dispose widgetu. Typický scénář: Navigator.of(context) uložený v proměnné a použitý poté, co uživatel opustil obrazovku. Řešení — neuchovávejte kontext ve statických nebo dlouho žijících objektech.
Bezpečnostní vzor pro práci s BuildContext v asynchronních operacích: vždy kontrolujte mounted před použitím kontextu a neuchovávejte kontext v uzávěrech, které mohou přežít widget:
Future<void> _safeNavigation(BuildContext context) async {
await Future.delayed(const Duration(seconds: 2));
if (!context.mounted) return;
Navigator.of(context).push(MaterialPageRoute(...));
}
Práce s BuildContext vyžaduje pochopení jeho životního cyklu a omezení. První pravidlo: používejte kontext pouze uvnitř metod, které jej přijímají jako parametr (build, didChangeDependencies). Neuchovávejte kontext v polích třídy nebo statických proměnných — to téměř vždy vede k chybám.
Druhé pravidlo: pro přístup k datům z InheritedWidget preferujte didChangeDependencies před buildem. Pokud jsou data potřebná pouze pro inicializaci, nikoli pro vykreslení, je didChangeDependencies správné místo. To umožňuje oddělit inicializační logiku od budování UI a vyhnout se opakovaným voláním při každé aktualizaci.
Třetí pravidlo: při práci s asynchronními operacemi používejte callbacky, které nejsou závislé na kontextu, nebo kontrolujte mounted. Pokud asynchronní operace vyžaduje navigaci nebo přístup k motivu, získejte tato data předem (v synchronním kontextu build nebo initState) a uložte je do lokálních proměnných, nikoli do kontextu.
Často kladené otázky
BuildContext — rozhraní představující pozici widgetu ve stromu elementů. Skrze něj widget získává přístup k okolí: motivu, media dotazům, navigátoru a datům z InheritedWidget. Každý widget má svůj vlastní jedinečný kontext.
BuildContext prochází strom od aktuálního elementu nahoru ke kořeni, nachází nejbližší InheritedWidget požadovaného typu. Metoda dependOnInheritedWidgetOfExactType nejen najde data, ale také přihlásí widget k odběru jejich změn — při aktualizaci InheritedWidget se widget automaticky znovu postaví.
BuildContext je vázán na element ve stromu a element může být zničen (widget odstraněn). Použití uchovaného kontextu po odstranění widgetu vede k výjimce. Pokud je kontext potřeba v asynchronním callbacku — kontrolujte mounted před použitím.
BuildContext je rozhraní, Element — implementace. Vývojář pracuje přes BuildContext, aniž by znal konkrétní typ elementu. Element — vnitřní mechanismus Flutteru spojující Widget s RenderObjectem a spravující životní cyklus.
Přímý přístup ke kontextu jiného widgetu neexistuje. Pro rodičovský kontext použijte context.findAncestorStateOfType pro State nebo klíče (GlobalKey). Pro potomka — předejte callback. BuildContext není určen pro mezividgetový přístup mimo hierarchii.
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é