BuildContext — bu nima, asosiy tushunchalar va ishlash prinsipi

Muallif: IT Sectr Nashr etilgan: 2026-07-01 O'qish vaqti: 9 daq

BuildContext — Flutter'ning asosiy obyekti bo'lib, ma'lum bir vidjetning elementlar daraxtidagi o'rnini ifodalaydi va uning muhitiga kirishni ta'minlaydi. Flutter rasmiy hujjatlariga ko'ra (Flutter.dev, 2026), BuildContext vidjet va freymvork o'rtasidagi ko'prikdir: u orqali vidjet mavzu (Theme), media so'rovlari (MediaQuery), lokalizatsiya (Localizations) va InheritedWidget ma'lumotlarini oladi. Har bir vidjet build metodiga birinchi argument sifatida uzatiladigan o'z BuildContext'iga ega.

Asosiy fikrlar

  • BuildContext — vidjetning elementlar daraxtidagi o'rnini ifodalovchi va uning iyerarxik muhitiga kirishni ta'minlovchi obyekt
  • InheritedWidget — BuildContext orqali mavjud bo'lgan, ma'lumotlarni daraxt bo'ylab pastga uzatishning asosiy mexanizmi
  • of() metodi — BuildContext'dan foydalanib daraxt bo'ylab yuqoriga eng yaqin InheritedWidget'ni qidiradigan statik metod (Theme.of, MediaQuery.of)
  • Kontekst va hayot sikli — BuildContext vidjet ko'chirilganda o'zgaradi; dispose'dan keyin kontekstga havola saqlanib qolishi mumkin emas
  • Xatolar — BuildContext'ni uning daraxtidan tashqarida yoki dispose'dan keyin ishlatish istisnolarga olib keladi (issiq qayta yuklashlar, asinxron qayta chaqiruvlar)

BuildContext nima?

BuildContext — Element klassi tomonidan amalga oshiriladigan interfeys bo'lib, vidjetga UI iyerarxiyasidagi joylashuvi haqida ma'lumot beradi. Har bir BuildContext namunasi daraxtdagi muayyan pozitsiya uchun noyobdir va boshqa joyga ko'chirilishi mumkin emas. Agar vidjet o'z ota-onasini o'zgartirsa (masalan, boshqa konteynerga ko'chirilsa), u yangi BuildContext oladi.

BuildContext'ning asosiy maqsadi — InheritedWidget'ga kirish. Kontekst orqali vidjet daraxt bo'ylab yuqoriga ko'tarilib, eng yaqin Theme, MediaQuery, Navigator yoki Directionality nusxasini topadi. Bu mexanizm Flutter'dagi barcha mavzu, navigatsiya va adaptiv layout tizimining asosidir. BuildContext'siz hech bir vidjet bu ma'lumotlarni ololmaydi.

Flutter arxitektura hujjatlariga ko'ra (Google, 2026), BuildContext shuningdek vidjet bilan bog'langan RenderObject obyektini qidirish, o'lchamlarni o'lchash va joylashtirish uchun ishlatiladi. findRenderObject() va size kabi metodlar aynan kontekst orqali mavjud. Kontekst shuningdek Localizations.of(context) orqali lokalizatsiyaga kirishni ta'minlaydi.

BuildContext — element, vidjet emas

Muhim arxitektura tushunchasi: BuildContext — Widget emas, balki Element tomonidan amalga oshiriladigan interfeysdir. Element Widget (konfiguratsiya) va RenderObject (haqiqiy ko'rinish) o'rtasidagi „yopishtiruvchi” dir. Hujjatlarda „vidjet konteksti” deyilganda, o'sha vidjetni boshqaradigan element nazarda tutiladi. build metodi aynan shunday kontekstni oladi — yaratilayotgan vidjetning konteksti, qaytarilgan bola vidjetlarniki emas.

BuildContext qanday ishlaydi?

BuildContext ishlash mexanizmi elementlar daraxtini pastdan yuqoriga aylanib chiqishga asoslangan. Vidjet Theme.of(context) ni chaqirganda, kontekst joriy elementdan boshlab ildiz tomon yuqoriga harakatlanadi va har bir elementni Theme turidagi InheritedWidget uchun tekshiradi. Topilgan birinchi InheritedWidget qaytariladi — bu vidjetning mavzuni eng yaqin ta'rifdan olishini kafolatlaydi.

Har bir BuildContext ota-kontekstga (parent) va bola kontekstlarga havolani saqlaydi. Bu daraxt bo'ylab ham yuqoriga (ota-onalarga), ham pastga (avlodlarga) harakatlanish imkonini beruvchi ikki tomonlama aloqadir. Flutter'da InheritedWidget qidirish uchun faqat yuqoriga harakat ishlatiladi — vidjet ma'lumotlarni faqat ajdodlardan olishi mumkin, avlodlardan emas. Bu fundamental arxitektura cheklovidir.

Flutter manba kodiga ko'ra (Flutter SDK, 2026), BuildContext quyidagi metodlarni o'z ichiga oladi: visitAncestorElements, visitChildElements, findAncestorWidgetOfExactType, dependOnInheritedWidgetOfExactType va getRenderObject. Oxirgi ikkitasi eng ko'p ishlatiladi: dependOnInheritedWidgetOfExactType nafaqat InheritedWidget'ni topadi, balki uning o'zgarishlariga obuna bo'ladi (vidjet InheritedWidget o'zgarganda qayta quriladi).

Kontekst orqali obuna

dependOnInheritedWidgetOfExactType — reaktivlikni ta'minlovchi BuildContext'ning asosiy metodi. Vidjet Theme.of(context) ni chaqirganda, u nafaqat mavzuni oladi — balki uning o'zgarishlariga obuna bo'ladi. Agar Theme o'zgarsa (masalan, qorong'i/yorug' mavzuni almashtirishda), barcha obuna bo'lgan vidjetlar avtomatik ravishda qayta quriladi. Bu Flutter'dagi reaktivlik mexanizmidir.

BuildContext vs Element

BuildContext — interfeys, Element esa — uning amalga oshirilishi. Flutter kodida siz doimo BuildContext interfeysi orqali ishlaysiz, elementning aniq turini bilmasdan (StatelessElement, StatefulElement, ProxyElement va boshq.). Bu ataylab qilingan: dasturchi elementni amalga oshirish tafsilotlarini bilishi shart emas — muhitga kirish uchun interfeys yetarli.

Har xil turdagi elementlar BuildContext'ni turlicha amalga oshiradi: StatelessElement shunchaki build chaqiruvlarini uzatadi, StatefulElement State'ni boshqaradi, InheritedElement esa dependOnInheritedWidgetOfExactType orqali obunalarni kuzatadi. Biroq dasturchi nuqtai nazaridan ularning barchasi yagona API'ga ega BuildContext'dir.

JihatBuildContextElement
TurInterfeys (abstract class)Amalga oshirish sinfi
FoydalanishDasturchi tomonidan build'daFlutter'ning ichki mexanizmi
Qidiruv metodlariof(), findAncestor...()mount, update, unmount
OchiqligiOchiq APIpackage-internal
Vidjet bilan bog'liqlikwidget maydoni orqaliWidget va state'ga egalik qiladi

Dart tilida kod misollari

Mavzu va media so'rovlariga kirish uchun BuildContext dan asosiy foydalanish:

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,
      ),
    );
  }
}

BuildContext orqali navigatsiya misoli. Navigator.of(context) kontekstdan foydalanib daraxt bo'ylab yuqoriga eng yaqin Navigator'ni qidiradi:

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'),
    );
  }
}

BuildContext orqali vidjet o'lchamini topish misoli. findRenderObject() metodi RenderObject qaytaradi, undan o'lchamni olish mumkin:

dart
void _printSize(BuildContext context) {
  final renderBox = context.findRenderObject() as RenderBox?;
  if (renderBox != null) {
    print('Widget size: ${renderBox.size}');
  }
}

Muhim: findRenderObject() vidjet hali o'rnatilmagan yoki allaqachon olib tashlangan bo'lsa, null qaytaradi. Ishlatishdan oldin har doim natijani null uchun tekshiring. Bu metodni build ichida qurish tugashidan oldin chaqirish ham null qaytarishi mumkin.

InheritedWidget va BuildContext

InheritedWidget — ma'lumotlarni BuildContext orqali daraxt bo'ylab pastga samarali tarqatadigan maxsus vidjetdir. Bola vidjet MyInheritedWidget.of(context) ni chaqirganda, BuildContext daraxt bo'ylab yuqoriga ko'tariladi, tegishli turdagi eng yaqin InheritedWidget'ni topadi va uning ma'lumotlarini qaytaradi. Bunda kontekst o'zgarishlarga obuna bo'ladi: agar InheritedWidget o'zgarsa, barcha obuna bo'lgan vidjetlar avtomatik ravishda qayta quriladi.

BuildContext + InheritedWidget birikmasi global o'zgaruvchilar va prop-drilling (ma'lumotlarni konstruktorlar zanjiri orqali uzatish) o'rnini bosadi. Mavzuni 10 darajadagi vidjetlar orqali uzatish o'rniga, har bir vidjet uni to'g'ridan-to'g'ri Theme.of(context) orqali olishi mumkin. Bu kodni tozaroq qiladi va uzatiladigan parametrlar sonini kamaytiradi.

Flutter Team'iga ko'ra (Google, aprel 2026), InheritedWidget shunchalik samarali mexanizmki, uning asosida barcha rasmiy holatni boshqarish yechimlari qurilgan: Provider InheritedWidget'ni o'rab oladi, Riverpod uni qatlamlardan biri sifatida ishlatadi, Flutter SDK'ning o'zi (Theme, MediaQuery, Navigator, Localizations) esa to'liq ushbu arxitekturaga asoslangan.

O'z InheritedWidget'ingizni yaratish

O'z InheritedWidget'ingizni yaratish tashqi bog'liqliklarsiz ma'lumotlarni tarqatish imkonini beradi. Sinf InheritedWidget'ni kengaytiradi va of(BuildContext context) statik metodini taqdim etadi. Bu oddiy stsenariylar uchun Provider'ga minimalist alternativadir:

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;
  }
}

Endi daraxt bo'ylab pastdagi har qanday vidjet konfiguratsiyaga kirish imkoniyatiga ega: final config = AppConfig.of(context);. Agar konfiguratsiya o'zgarsa, barcha obuna bo'lgan vidjetlar avtomatik ravishda qayta quriladi.

Oddiy xatolar

Birinchi oddiy xato — BuildContext'ni dispose'dan keyin saqlash yoki mounted tekshiruvisiz asinxron qayta chaqiruvda ishlatish. BuildContext elementga bog'langan va element yo'q qilinishi mumkin (vidjet daraxtdan olib tashlanganda). Element yo'q qilinganidan keyin kontekstdan foydalanish istisnoga olib keladi. Yechim — context.mounted (Flutter'ning yangi versiyalarida mavjud) yoki State'da mounted ni tekshirish.

Ikkinchi xato — initState'da Theme.of(context) ni chaqirish. initState bosqichida kontekst hali daraxtda to'liq o'rnatilmagan. initState'da InheritedWidget qidirish null qaytarishi yoki istisno tashlashi mumkin. Barcha of(context) chaqiruvlari build yoki didChangeDependencies'da bajarilishi kerak, bu yerda kontekst daraxtda bo'lishi kafolatlanadi.

Uchinchi xato — bir vidjetning BuildContext'idan boshqa vidjetni boshqarish uchun foydalanish. BuildContext „ota-bola” iyerarxiyasidan tashqarida vidjetlararo o'zaro ta'sir uchun mo'ljallanmagan. Agar boshqa vidjetning holatini boshqarish kerak bo'lsa — qayta chaqiruvlar, kontrollerlar yoki holatni boshqarish vositalaridan foydalaning.

To'rtinchi xato — BuildContext'ni vidjetning dispose'idan o'tib ketadigan asinxron funksiyaga uzatish. Oddiy stsenariy: Navigator.of(context) o'zgaruvchida saqlanadi va foydalanuvchi ekranni tark etganidan keyin ishlatiladi. Yechim — kontekstni statik yoki uzoq umrli obyektlarda saqlamang.

Asinxron operatsiyalarda kontekst

BuildContext bilan asinxron operatsiyalarda ishlash uchun xavfsizlik namunasi: kontekstdan foydalanishdan oldin har doim mounted ni tekshiring va kontekstni vidjetdan uzoqroq yashashi mumkin bo'lgan yopilishlarda saqlamang:

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

Eng yaxshi amaliyotlar

BuildContext bilan ishlash uning hayot siklini va cheklovlarini tushunishni talab qiladi. Birinchi qoida: kontekstdan faqat uni parametr sifatida qabul qiladigan metodlar ichida foydalaning (build, didChangeDependencies). Kontekstni sinf maydonlarida yoki statik o'zgaruvchilarda saqlamang — bu deyarli har doim xatolarga olib keladi.

Ikkinchi qoida: InheritedWidget ma'lumotlariga kirish uchun build o'rniga didChangeDependencies'ni afzal ko'ring. Agar ma'lumotlar faqat ishga tushirish uchun kerak bo'lsa, render uchun emas, didChangeDependencies to'g'ri joydir. Bu ishga tushirish mantiqini UI qurilishidan ajratish va har bir yangilanishda takroriy chaqiruvlarning oldini olish imkonini beradi.

Uchinchi qoida: asinxron operatsiyalar bilan ishlaganda kontekstga bog'liq bo'lmagan qayta chaqiruvlardan foydalaning yoki mounted ni tekshiring. Agar asinxron operatsiya navigatsiya yoki mavzuga kirishni talab qilsa, bu ma'lumotlarni oldindan (sinxron build yoki initState kontekstida) oling va kontekstda emas, balki mahalliy o'zgaruvchilarda saqlang.

Kontekst qachon kerak va qachon kerak emas

  • Kerak: Theme, MediaQuery, Navigator, Localizations, ScaffoldMessenger'ga kirish
  • Kerak: o'lchamlarni o'lchash uchun RenderObject qidirish
  • Kerak: SnackBar, BottomSheet, Dialog yaratish
  • Kerak emas: biznes mantiq metodlarini chaqirish, HTTP so'rovlari, ma'lumotlar bazasi bilan ishlash
  • Kerak emas: build'dan tashqarida vidjetlarni qurish (fabrikalarda, konstruktorlarda)

Ko'p beriladigan savollar

Flutter'da BuildContext nima?

BuildContext — vidjetning elementlar daraxtidagi o'rnini ifodalovchi interfeys. U orqali vidjet muhitga kirish oladi: mavzu, media so'rovlari, navigator va InheritedWidget ma'lumotlari. Har bir vidjet o'zining noyob kontekstiga ega.

BuildContext qanday ishlaydi?

BuildContext daraxtni joriy elementdan ildizga qadar aylanib chiqadi va so'ralgan turdagi eng yaqin InheritedWidget'ni topadi. dependOnInheritedWidgetOfExactType metodi nafaqat ma'lumotlarni topadi, balki vidjetni ularning o'zgarishlariga obuna qiladi — InheritedWidget yangilanganda vidjet avtomatik qayta quriladi.

Nega BuildContext sinf maydonlarida saqlanmasligi kerak?

BuildContext daraxtdagi elementga bog'langan va element yo'q qilinishi mumkin (vidjet olib tashlanganda). Saqlangan kontekstdan vidjet olib tashlanganidan keyin foydalanish istisnoga olib keladi. Agar kontekst asinxron qayta chaqiruvda kerak bo'lsa — ishlatishdan oldin mounted ni tekshiring.

BuildContext va Element o'rtasidagi farq nima?

BuildContext — interfeys, Element esa — amalga oshirish. Dasturchi BuildContext orqali ishlaydi, elementning aniq turini bilmagan holda. Element — Widget'ni RenderObject bilan bog'laydigan va hayot siklini boshqaradigan Flutter'ning ichki mexanizmi.

Boshqa vidjetning BuildContext'ini olish mumkinmi?

Boshqa vidjetning kontekstiga to'g'ridan-to'g'ri kirish yo'q. Ota konteksti uchun State uchun context.findAncestorStateOfType yoki kalitlardan (GlobalKey) foydalaning. Bola uchun — qayta chaqiruvni uzating. BuildContext iyerarxiyadan tashqarida vidjetlararo kirish uchun mo'ljallanmagan.

Xulosa

  • BuildContext — vidjetning daraxtdagi o'rnini ifodalovchi va InheritedWidget orqali iyerarxik muhitga kirishni ta'minlovchi Flutter'ning asosiy obyekti
  • Qidiruv mexanizmi — BuildContext daraxtni pastdan yuqoriga aylanib chiqadi, so'ralgan turdagi eng yaqin InheritedWidget'ni topadi va uning o'zgarishlariga obuna bo'ladi
  • Asosiy foydalanish — mavzular, moslashuvchanlik va navigatsiyaga kirish uchun Theme.of(context), MediaQuery.of(context), Navigator.of(context)
  • BuildContext vs Element — BuildContext ochiq interfeys, Element — xususiy amalga oshirish. Dasturchi har doim BuildContext orqali ishlaydi
  • Hayot sikli — BuildContext mos element yashar ekan, yashaydi; dispose'dan keyin kontekstdan foydalanilmasligi kerak
  • Xatolar — kontekstni uzoq umrli obyektlarda saqlash, initState'da ishlatish, dispose'dan keyin ishlatish — tez-tez uchraydigan xato manbalari
  • Qoida — BuildContext'dan faqat build/didChangeDependencies ichida foydalaning, uni saqlamang, asinxron stsenariylarda mounted ni tekshiring

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing