BuildContext — co to je, klíčové pojmy a princip práce

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

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 — objekt představující pozici widgetu ve stromu elementů a zajišťující přístup k jeho hierarchickému okolí
  • InheritedWidget — hlavní mechanismus předávání dat dolů stromem, přístupný přes BuildContext
  • Metoda of() — statická metoda používající BuildContext k vyhledání nejbližšího InheritedWidget nahoru stromem (Theme.of, MediaQuery.of)
  • Kontext a životní cyklus — BuildContext se mění při přesunu widgetu; odkaz na kontext nelze uchovávat po dispose
  • Chyby — použití BuildContext mimo jeho strom nebo po dispose vede k výjimkám (hot reload, asynchronní callbacky)

Co je BuildContext?

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).

BuildContext je element, ne widget

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ů.

Jak funguje BuildContext?

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).

Přihlášení k odběru přes kontext

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 vs Element

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.

AspektBuildContextElement
TypRozhraní (abstract class)Třída implementace
PoužitíVývojářem v buildVnitřní mechanismus Flutteru
Metody vyhledáváníof(), findAncestor...()mount, update, unmount
VeřejnostVeřejné APIpackage-internal
Spojení s widgetemPřes pole widgetVlastní widget a state

Příklady kódu v Dartu

Základní použití BuildContext pro přístup k motivu a media dotazům:

dart
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:

dart
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:

dart
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 a BuildContext

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

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:

dart
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.

Typické chyby

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.

Kontext v asynchronních operacích

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:

dart
Future<void> _safeNavigation(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 2));
  if (!context.mounted) return;
  Navigator.of(context).push(MaterialPageRoute(...));
}

Nejlepší praktiky

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.

Kdy je kontext potřeba a kdy ne

  • Potřeba: přístup k Theme, MediaQuery, Navigator, Localizations, ScaffoldMessenger
  • Potřeba: vyhledání RenderObject pro měření rozměrů
  • Potřeba: vytvoření SnackBar, BottomSheet, Dialog
  • Není potřeba: volání metod business logiky, HTTP požadavky, práce s databází
  • Není potřeba: konstrukce widgetů mimo build (v továrnách, konstruktorech)

Často kladené otázky

Co je BuildContext ve Flutteru?

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.

Jak funguje BuildContext?

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í.

Proč nelze BuildContext uchovávat v polích třídy?

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.

Jaký je rozdíl mezi BuildContext a Element?

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.

Lze získat BuildContext jiného widgetu?

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í

  • BuildContext — fundamentální objekt Flutteru představující pozici widgetu ve stromu a poskytující přístup k hierarchickému okolí přes InheritedWidget
  • Mechanismus vyhledávání — BuildContext prochází strom zdola nahoru, nachází nejbližší InheritedWidget požadovaného typu a přihlašuje se k odběru jeho změn
  • Hlavní použití — Theme.of(context), MediaQuery.of(context), Navigator.of(context) pro přístup k motivům, adaptivitě a navigaci
  • BuildContext vs Element — BuildContext je veřejné rozhraní, Element — soukromá implementace. Vývojář vždy pracuje přes BuildContext
  • Životní cyklus — BuildContext žije, dokud žije odpovídající element; po dispose by kontext neměl být používán
  • Chyby — uchovávání kontextu v dlouho žijících objektech, použití v initState, použití po dispose — časté zdroje chyb
  • Pravidlo — používejte BuildContext pouze uvnitř build/didChangeDependencies, neuchovávejte jej, kontrolujte mounted v asynchronních scénáří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é