BuildContext — фундаментални објекат Flutter-а који представља положај одређеног виџета у стаблу елемената и пружа приступ његовом окружењу. Према званичној документацији Flutter-а (Flutter.dev, 2026), BuildContext је мост између виџета и фрејмворка: кроз њега виџет добија тему (Theme), медија упите (MediaQuery), локализацију (Localizations) и податке од InheritedWidget-а. Сваки виџет има свој BuildContext, који се прослеђује методи build као први аргумент.
Главно
BuildContext — је интерфејс који имплементира класа Element, који пружа виџету информације о његовој локацији у хијерархији UI. Свака инстанца BuildContext-а је јединствена за одређену позицију у стаблу и не може бити премештена на друго место. Ако виџет промени свог родитеља (нпр. буде премештен у други контејнер), добија нови BuildContext.
Основна намена BuildContext-а је приступ InheritedWidget-у. Кроз контекст виџет проналази најближу инстанцу Theme, MediaQuery, Navigator или Directionality, подижући се уз стабло. Овај механизам лежи у основи целог система тема, навигације и адаптивног распореда у Flutter-у. Без BuildContext-а ниједан виџет не може добити ове податке.
Према Flutter architectural docs (Google, 2026), BuildContext се такође користи за проналажење RenderObject објекта повезаног са виџетом, за мерење димензија и позиционирање. Методе попут findRenderObject() и size доступне су управо кроз контекст. Контекст такође пружа приступ локализацији кроз Localizations.of(context).
Важно архитектонско разумевање: BuildContext је интерфејс који имплементира Element, а не Widget. Element је „лепак“ између Widget-а (конфигурације) и RenderObject-а (стварног приказа). Када се у документацији каже „контекст виџета“ — мисли се на елемент који управља тим виџетом. Метода build добија управо такав контекст — контекст виџета који се ствара, а не враћених виџета потомака.
Механизам рада BuildContext-а заснива се на обиласку стабла елемената одоздо према горе. Када виџет позове Theme.of(context), контекст започиње претрагу од тренутног елемента и креће се навише ка корену, проверавајући сваки елемент на присуство InheritedWidget-а са типом Theme. Први пронађени InheritedWidget се враћа — то гарантује да виџет добија тему из најближе дефиниције.
Сваки BuildContext чува референцу на родитељски контекст (parent) и на контексте потомака. Ово је двосмерна веза која омогућава кретање по стаблу и навише (ка родитељима) и наниже (ка потомцима). У Flutter-у се за претрагу InheritedWidget-а користи само кретање навише — виџет може добити податке само од предака, не од потомака. Ово је фундаментално архитектонско ограничење.
Према Flutter изворном коду (Flutter SDK, 2026), BuildContext садржи методе: visitAncestorElements, visitChildElements, findAncestorWidgetOfExactType, dependOnInheritedWidgetOfExactType и getRenderObject. Последње две су најчешће коришћене: dependOnInheritedWidgetOfExactType не само да проналази InheritedWidget, већ се и претплаћује на његове промене (виџет ће бити поново изграђен када се InheritedWidget промени).
dependOnInheritedWidgetOfExactType — кључна метода BuildContext-а која обезбеђује реактивност. Када виџет позове Theme.of(context), он не само да добија тему — он се претплаћује на њене промене. Ако се Theme промени (нпр. при пребацивању тамне/светле теме), сви претплаћени виџети се аутоматски поново изграђују. То је механизам реактивности у Flutter-у.
BuildContext је интерфејс, а Element — његова имплементација. У Flutter коду увек радите кроз интерфејс BuildContext, не знајући конкретан тип елемента (StatelessElement, StatefulElement, ProxyElement итд.). Ово је намерно урађено: програмер не мора да зна детаље имплементације елемента — довољан је интерфејс за приступ окружењу.
Различити типови елемената различито имплементирају BuildContext: StatelessElement само прослеђује позиве build-а, StatefulElement управља State-ом, а InheritedElement прати претплате кроз dependOnInheritedWidgetOfExactType. Међутим, са становишта програмера, сви су они BuildContext са јединственим API-јем.
| Аспект | BuildContext | Element |
|---|---|---|
| Тип | Интерфејс (abstract class) | Класа имплементације |
| Употреба | Од стране програмера у build-у | Унутрашњи механизам Flutter-а |
| Методе претраге | of(), findAncestor...() | mount, update, unmount |
| Јавност | Јавни API | package-internal |
| Веза са виџетом | Кроз widget поље | Поседује widget и state |
Основна употреба BuildContext-а за приступ теми и медија упитима:
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,
),
);
}
}
Пример са навигацијом кроз BuildContext. Navigator.of(context) користи контекст за проналажење најближег Navigator-а уз стабло:
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'),
);
}
}
Пример проналажења величине виџета кроз BuildContext. Метода findRenderObject() враћа RenderObject из којег се може добити величина:
void _printSize(BuildContext context) {
final renderBox = context.findRenderObject() as RenderBox?;
if (renderBox != null) {
print('Widget size: ${renderBox.size}');
}
}
Важно: findRenderObject() враћа null ако виџет још није монтиран или је већ демонтиран. Увек проверавајте резултат на null пре употребе. Позивање ове методе унутар build-а пре завршетка изградње такође може вратити null.
InheritedWidget — специјални виџет који ефикасно распростире податке низ стабло кроз BuildContext. Када виџет потомак позове MyInheritedWidget.of(context), BuildContext се пење уз стабло, проналази најближи InheritedWidget одговарајућег типа и враћа његове податке. При томе се контекст претплаћује на промене: ако се InheritedWidget промени, сви претплаћени виџети се аутоматски поново изграђују.
Комбинација BuildContext + InheritedWidget замењује глобалне променљиве и prop-drilling (пренос података кроз ланац конструктора). Уместо да преносите тему кроз 10 нивоа виџета, сваки виџет је може добити директно кроз Theme.of(context). То чини код чистијим и смањује број прослеђених параметара.
Према Flutter Team-у (Google, април 2026), InheritedWidget је толико ефикасан механизам да су на њему заснована сва званична решења за управљање стањем: Provider облаже InheritedWidget, Riverpod га користи као један од слојева, а сам Flutter SDK (Theme, MediaQuery, Navigator, Localizations) је у потпуности заснован на овој архитектури.
Прављење сопственог InheritedWidget-а омогућава ширење података без спољних зависности. Класа проширује InheritedWidget и пружа статички метод of(BuildContext context). Ово је минималистичка алтернатива Provider-у за једноставне сценарије:
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;
}
}
Сада сваки виџет ниже у стаблу може приступити конфигурацији: final config = AppConfig.of(context);. Ако се конфигурација промени, сви претплаћени виџети ће бити аутоматски поново изграђени.
Прва типична грешка — чување BuildContext-а после dispose или коришћење у асинхроном повратном позиву без провере mounted. BuildContext је везан за елемент, а елемент може бити уништен (при уклањању виџета из стабла). Коришћење контекста после уништења елемента доводи до изузетка. Решење — користити context.mounted (доступан у новијим верзијама Flutter-а) или проверавати mounted у State-у.
Друга грешка — позивање Theme.of(context) у initState-у. У фази initState контекст још није у потпуности монтиран у стаблу. Претрага InheritedWidget-а у initState-у може вратити null или бацити изузетак. Сви of(context) позиви треба да се извршавају у build-у или didChangeDependencies-у, где је контекст гарантовано у стаблу.
Трећа грешка — коришћење BuildContext-а из једног виџета за манипулацију другим виџетом. BuildContext није намењен за међувиџетску интеракцију ван хијерархије „родитељ-потомак“. Ако је потребно управљати стањем другог виџета — користите повратне позиве, контролере или алате за управљање стањем.
Четврта грешка — прослеђивање BuildContext-а асинхроној функцији која надживљава dispose виџета. Типичан сценарио: Navigator.of(context) сачуван у променљивој и коришћен након што је корисник напустио екран. Решење — не чувати контекст у статичким или дугоживућим објектима.
Безбедносни образац за рад са BuildContext-ом у асинхроним операцијама: увек проверавати mounted пре коришћења контекста и не чувати контекст у затворењима која могу надживети виџет:
Future<void> _safeNavigation(BuildContext context) async {
await Future.delayed(const Duration(seconds: 2));
if (!context.mounted) return;
Navigator.of(context).push(MaterialPageRoute(...));
}
Рад са BuildContext-ом захтева разумевање његовог животног циклуса и ограничења. Прво правило: користите контекст само унутар метода које га добијају као параметар (build, didChangeDependencies). Не чувајте контекст у пољима класе или статичким променљивим — то готово увек доводи до грешака.
Друго правило: за приступ подацима из InheritedWidget-а преферирајте didChangeDependencies уместо build-а. Ако су подаци потребни само за иницијализацију, а не за приказивање, didChangeDependencies је право место. То омогућава одвајање логике иницијализације од изградње UI-ја и избегавање поновљених позива при сваком ажурирању.
Треће правило: при раду са асинхроним операцијама користите повратне позиве који не зависе од контекста или проверавајте mounted. Ако асинхрона операција захтева навигацију или приступ теми, добијте ове податке унапред (у синхроном контексту build-а или initState-а) и сачувајте их у локалним променљивим, а не у контексту.
Често постављана питања
BuildContext — интерфејс који представља положај виџета у стаблу елемената. Кроз њега виџет добија приступ окружењу: теми, медија упитима, навигатору и подацима од InheritedWidget-а. Сваки виџет има свој јединствени контекст.
BuildContext обилази стабло од тренутног елемента навише ка корену, проналазећи најближи InheritedWidget затраженог типа. Метода dependOnInheritedWidgetOfExactType не само да проналази податке, већ и претплаћује виџет на њихове промене — при ажурирању InheritedWidget-а виџет се аутоматски поново изграђује.
BuildContext је везан за елемент у стаблу, а елемент може бити уништен (виџет уклоњен). Коришћење сачуваног контекста после уклањања виџета доводи до изузетка. Ако је контекст потребан у асинхроном повратном позиву — проверавајте mounted пре употребе.
BuildContext је интерфејс, Element — имплементација. Програмер ради кроз BuildContext, не знајући конкретан тип елемента. Element — унутрашњи механизам Flutter-а који повезује Widget са RenderObject-ом и управља животним циклусом.
Директног приступа контексту другог виџета нема. За родитељски контекст користите context.findAncestorStateOfType за State или кључеве (GlobalKey). За потомак — проследите повратни позив. BuildContext није намењен за међувиџетски приступ ван хијерархије.
Завршни преглед
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође