BuildContext — یہ کیا ہے، کلیدی تصورات اور کام کا اصول

مصنف: IT Sectr اشاعت: 2026-07-01 مطالعے کا وقت: 9 منٹ

BuildContext — Flutter میں ایک بنیادی آبجیکٹ ہے جو کسی مخصوص ویجیٹ کی ایلیمنٹس کے درخت میں پوزیشن کو ظاہر کرتا ہے اور اس کے ماحول تک رسائی فراہم کرتا ہے۔ Flutter کی سرکاری دستاویزات (Flutter.dev, 2026) کے مطابق، BuildContext ویجیٹ اور فریم ورک کے درمیان ایک پل ہے: اس کے ذریعے ویجیٹ تھیم (Theme)، میڈیا کوریز (MediaQuery)، لوکلائزیشن (Localizations) اور InheritedWidget سے ڈیٹا حاصل کرتا ہے۔ ہر ویجیٹ کا اپنا BuildContext ہوتا ہے، جو build طریقہ کار میں پہلے آرگومینٹ کے طور پر منتقل کیا جاتا ہے۔

اہم نکات

  • BuildContext — ایک آبجیکٹ جو ویجیٹ کی ایلیمنٹس کے درخت میں پوزیشن کو ظاہر کرتا ہے اور اس کے درجہ بندی کے ماحول تک رسائی فراہم کرتا ہے
  • InheritedWidget — درخت میں نیچے ڈیٹا منتقل کرنے کا بنیادی طریقہ کار، جس تک رسائی BuildContext کے ذریعے حاصل کی جاتی ہے
  • of() طریقہ — ایک جامد طریقہ جو BuildContext کا استعمال کرتے ہوئے درخت میں اوپر کی طرف قریب ترین InheritedWidget تلاش کرتا ہے (Theme.of, MediaQuery.of)
  • سیاق و سباق اور لائف سائیکل — BuildContext ویجیٹ کی منتقلی کے ساتھ بدلتا ہے؛ dispose کے بعد سیاق و سباق کا حوالہ محفوظ نہیں کیا جا سکتا
  • غلطیاں — BuildContext کو اس کے درخت سے باہر یا dispose کے بعد استعمال کرنا مستثنیات کا باعث بنتا ہے (ہاٹ ریلوڈ، غیر متوقع کال بیکس)

BuildContext کیا ہے؟

BuildContext — ایک انٹرفیس ہے جسے Element کلاس لاگو کرتی ہے، اور یہ ویجیٹ کو UI کے درجہ بندی میں اس کے مقام کے بارے میں معلومات فراہم کرتا ہے۔ BuildContext کی ہر مثال درخت میں کسی مخصوص پوزیشن کے لیے منفرد ہوتی ہے اور اسے کسی دوسری جگہ منتقل نہیں کیا جا سکتا۔ اگر ویجیٹ اپنے والدین کو بدلتا ہے (مثلاً، کسی دوسرے کنٹینر میں منتقل ہوتا ہے)، تو اسے ایک نیا BuildContext ملتا ہے۔

BuildContext کا بنیادی مقصد InheritedWidget تک رسائی ہے۔ سیاق و سباق کے ذریعے ویجیٹ Theme, MediaQuery, Navigator یا Directionality کی قریب ترین مثال تلاش کرتا ہے، درخت میں اوپر کی طرف بڑھتے ہوئے۔ یہ طریقہ کار Flutter میں تمام تھیمز، نیویگیشن اور ریسپانسیو لے آؤٹ کی بنیاد ہے۔ BuildContext کے بغیر کوئی بھی ویجیٹ یہ ڈیٹا حاصل نہیں کر سکتا۔

Flutter آرکیٹیکچرل دستاویزات (Google, 2026) کے مطابق، BuildContext کا استعمال ویجیٹ سے منسلک RenderObject آبجیکٹ کو تلاش کرنے کے لیے بھی کیا جاتا ہے، تاکہ سائز کی پیمائش اور پوزیشننگ کی جا سکے۔ findRenderObject() اور size جیسے طریقے سیاق و سباق کے ذریعے دستیاب ہیں۔ سیاق و سباق Localizations.of(context) کے ذریعے لوکلائزیشن تک بھی رسائی فراہم کرتا ہے۔

BuildContext ایک ایلیمنٹ ہے، ویجیٹ نہیں

اہم آرکیٹیکچرل سمجھ: BuildContext ایک انٹرفیس ہے جسے Element لاگو کرتا ہے، Widget نہیں۔ Element Widget (کنفیگریشن) اور RenderObject (حقیقی ڈسپلے) کے درمیان «گلو» ہے۔ جب دستاویزات میں «ویجیٹ کا سیاق و سباق» کہا جاتا ہے، تو اس سے مراد وہ ایلیمنٹ ہے جو اس ویجیٹ کو کنٹرول کرتا ہے۔ build طریقہ کار وہی سیاق و سباق حاصل کرتا ہے — تخلیق کیے جانے والے ویجیٹ کا سیاق و سباق، نہ کہ واپس کیے گئے بچوں کے ویجیٹس کا۔

BuildContext کیسے کام کرتا ہے؟

BuildContext کے کام کرنے کا طریقہ کار ایلیمنٹس کے درخت کو نیچے سے اوپر کی طرف گھومنے پر مبنی ہے۔ جب ویجیٹ Theme.of(context) کال کرتا ہے، تو سیاق و سباق موجودہ ایلیمنٹ سے تلاش شروع کرتا ہے اور جڑ کی طرف اوپر بڑھتا ہے، ہر ایلیمنٹ کو Theme قسم کے InheritedWidget کی موجودگی کے لیے چیک کرتا ہے۔ پہلا ملا 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

BuildContext ایک انٹرفیس ہے، جبکہ Element اس کا نفاذ ہے۔ Flutter کوڈ میں آپ ہمیشہ BuildContext انٹرفیس کے ذریعے کام کرتے ہیں، ایلیمنٹ کی مخصوص قسم (StatelessElement, StatefulElement, ProxyElement وغیرہ) کو جانے بغیر۔ یہ جان بوجھ کر کیا گیا ہے: ڈویلپر کو ایلیمنٹ کے نفاذ کی تفصیلات جاننے کی ضرورت نہیں — ماحول تک رسائی کے لیے انٹرفیس کافی ہے۔

مختلف اقسام کے ایلیمنٹس BuildContext کو مختلف طریقے سے لاگو کرتے ہیں: StatelessElement صرف build کالز منتقل کرتا ہے، StatefulElement State کا انتظام کرتا ہے، اور InheritedElement dependOnInheritedWidgetOfExactType کے ذریعے سبسکرپشنز کو ٹریک کرتا ہے۔ تاہم ڈویلپر کے نقطہ نظر سے یہ سب ایک ہی BuildContext ہیں جس میں یکساں API ہے۔

پہلوBuildContextElement
قسمانٹرفیس (abstract class)نفاذی کلاس
استعمالڈویلپر کے ذریعے build میںFlutter کا داخلی طریقہ کار
تلاش کے طریقےof(), findAncestor...()mount, update, unmount
عوامی حیثیتعوامی APIpackage-internal
ویجیٹ سے تعلقwidget فیلڈ کے ذریعےwidget اور state کا مالک

Dart میں کوڈ کی مثالیں

تھیم اور میڈیا کوریز تک رسائی کے لیے BuildContext کا بنیادی استعمال:

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(
        'اسٹائلڈ ٹیکسٹ',
        style: theme.textTheme.headlineMedium,
      ),
    );
  }
}

BuildContext کے ذریعے نیویگیشن کی مثال۔ Navigator.of(context) درخت میں اوپر کی طرف قریب ترین Navigator تلاش کرنے کے لیے سیاق و سباق کا استعمال کرتا ہے:

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('تفصیلات پر جائیں'),
    );
  }
}

BuildContext کے ذریعے ویجیٹ کا سائز تلاش کرنے کی مثال۔ findRenderObject() طریقہ RenderObject واپس کرتا ہے، جس سے سائز حاصل کیا جا سکتا ہے:

dart
void _printSize(BuildContext context) {
  final renderBox = context.findRenderObject() as RenderBox?;
  if (renderBox != null) {
    print('ویجیٹ کا سائز: ${renderBox.size}');
  }
}

اہم: findRenderObject() null واپس کرتا ہے اگر ویجیٹ ابھی ماؤنٹ نہیں ہوا یا پہلے ہی ان ماؤنٹ ہو چکا ہے۔ استعمال سے پہلے ہمیشہ null کے لیے نتیجہ چیک کریں۔ build کے اندر تعمیر مکمل ہونے سے پہلے اس طریقے کو کال کرنا بھی null واپس کر سکتا ہے۔

InheritedWidget اور BuildContext

InheritedWidget — ایک خاص ویجیٹ ہے جو BuildContext کے ذریعے درخت میں نیچے ڈیٹا کو مؤثر طریقے سے پھیلاتا ہے۔ جب بچہ ویجیٹ MyInheritedWidget.of(context) کال کرتا ہے، تو BuildContext درخت میں اوپر جاتا ہے، متعلقہ قسم کا قریب ترین InheritedWidget تلاش کرتا ہے اور اس کا ڈیٹا واپس کرتا ہے۔ اس دوران سیاق و سباق تبدیلیوں پر سبسکرائب ہو جاتا ہے: اگر InheritedWidget بدلتا ہے، تو تمام سبسکرائب شدہ ویجیٹس خود بخود دوبارہ تعمیر ہو جاتے ہیں۔

BuildContext + InheritedWidget کا امتزاج عالمی متغیرات اور پراپ ڈرلنگ (کنسٹرکٹرز کی زنجیر کے ذریعے ڈیٹا منتقل کرنا) کی جگہ لیتا ہے۔ تھیم کو 10 سطحوں کے ویجیٹس کے ذریعے منتقل کرنے کے بجائے، ہر ویجیٹ اسے براہ راست Theme.of(context) کے ذریعے حاصل کر سکتا ہے۔ یہ کوڈ کو صاف ستھرا بناتا ہے اور منتقل کردہ پیرامیٹرز کی تعداد کو کم کرتا ہے۔

Flutter ٹیم (Google, اپریل 2026) کے مطابق، InheritedWidget اتنا مؤثر طریقہ کار ہے کہ اس کی بنیاد پر اسٹیٹ مینجمنٹ کے تمام سرکاری حل بنائے گئے ہیں: Provider InheritedWidget کو لپیٹتا ہے، Riverpod اسے ایک پرت کے طور پر استعمال کرتا ہے، اور خود Flutter SDK (Theme, MediaQuery, Navigator, Localizations) مکمل طور پر اس آرکیٹیکچر پر مبنی ہے۔

اپنا InheritedWidget بنانا

اپنا خود کا InheritedWidget بنانا بیرونی انحصار کے بغیر ڈیٹا پھیلانے کی اجازت دیتا ہے۔ کلاس InheritedWidget کو بڑھاتی ہے اور ایک جامد طریقہ of(BuildContext context) فراہم کرتی ہے۔ یہ سادہ منظرناموں کے لیے Provider کا ایک کم سے کم متبادل ہے:

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

اب درخت میں نیچے کوئی بھی ویجیٹ کنفیگریشن تک رسائی حاصل کر سکتا ہے: final config = AppConfig.of(context);۔ اگر کنفیگریشن بدلتی ہے، تو تمام سبسکرائب شدہ ویجیٹس خود بخود دوبارہ تعمیر ہو جائیں گے۔

عام غلطیاں

پہلی عام غلطی — BuildContext کو dispose کے بعد محفوظ رکھنا یا بغیر mounted چیک کیے اسے غیر متوقع کال بیک میں استعمال کرنا۔ BuildContext ایلیمنٹ سے منسلک ہوتا ہے، اور ایلیمنٹ ختم ہو سکتا ہے (ویجیٹ کو درخت سے ہٹانے پر)۔ ایلیمنٹ کی تباہی کے بعد سیاق و سباق کا استعمال مستثنیات کا باعث بنتا ہے۔ حل — context.mounted استعمال کریں (Flutter کے نئے ورژنز میں دستیاب) یا State میں mounted چیک کریں۔

دوسری غلطی — initState میں Theme.of(context) کال کرنا۔ initState مرحلے پر سیاق و سباق ابھی درخت میں مکمل طور پر ماؤنٹ نہیں ہوا ہے۔ initState میں InheritedWidget کی تلاش null واپس کر سکتی ہے یا مستثنیٰ پھینک سکتی ہے۔ تمام of(context) کالز build یا didChangeDependencies میں کی جانی چاہئیں، جہاں سیاق و سباق درخت میں ہونے کی ضمانت ہے۔

تیسری غلطی — ایک ویجیٹ کے BuildContext کا استعمال دوسرے ویجیٹ میں ہیرا پھیری کے لیے۔ BuildContext «والدین-اولاد» کے درجہ بندی سے باہر باہمی ویجیٹ رابطے کے لیے نہیں بنایا گیا ہے۔ اگر کسی دوسرے ویجیٹ کی حالت کو کنٹرول کرنا ہے — تو کال بیکس، کنٹرولرز یا اسٹیٹ مینجمنٹ ٹولز استعمال کریں۔

چوتھی غلطی — BuildContext کو ایک غیر متوقع فنکشن میں منتقل کرنا جو ویجیٹ کے dispose سے زیادہ زندہ رہتا ہے۔ عام منظر نامہ: Navigator.of(context) کو ایک متغیر میں محفوظ کیا گیا اور صارف کے اسکرین چھوڑنے کے بعد استعمال کیا گیا۔ حل — سیاق و سباق کو جامد یا دیرپا آبجیکٹس میں محفوظ نہ کریں۔

غیر متوقع کارروائیوں میں سیاق و سباق

BuildContext کے ساتھ غیر متوقع کارروائیوں میں کام کرنے کا حفاظتی نمونہ: سیاق و سباق استعمال کرنے سے پہلے ہمیشہ mounted چیک کریں اور سیاق و سباق کو ایسے بندشوں میں محفوظ نہ کریں جو ویجیٹ سے زیادہ زندہ رہ سکتے ہیں:

dart
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 سے ڈیٹا تک رسائی کے لیے build کی بجائے didChangeDependencies ترجیح دیں۔ اگر ڈیٹا صرف ابتدائیہ کے لیے درکار ہے، نہ کہ ڈسپلے کے لیے، تو didChangeDependencies صحیح جگہ ہے۔ یہ ابتدائیہ کی منطق کو UI کی تعمیر سے الگ کرنے اور ہر اپ ڈیٹ پر بار بار کالز سے بچنے کی اجازت دیتا ہے۔

تیسرا اصول: غیر متوقع کارروائیوں کے ساتھ کام کرتے وقت کال بیکس استعمال کریں جو سیاق و سباق پر منحصر نہ ہوں، یا mounted چیک کریں۔ اگر غیر متوقع کارروائی کو نیویگیشن یا تھیم تک رسائی درکار ہے، تو یہ ڈیٹا پہلے سے (مطابقت پذیر build یا initState سیاق و سباق میں) حاصل کریں اور اسے سیاق و سباق کی بجائے مقامی متغیرات میں محفوظ کریں۔

سیاق و سباق کب ضروری ہے اور کب نہیں

  • ضروری: Theme, MediaQuery, Navigator, Localizations, ScaffoldMessenger تک رسائی
  • ضروری: سائز کی پیمائش کے لیے RenderObject تلاش کرنا
  • ضروری: SnackBar, BottomSheet, Dialog بنانا
  • ضروری نہیں: بزنس منطق کے طریقوں کو کال کرنا، HTTP درخواستیں، ڈیٹا بیس کے ساتھ کام
  • ضروری نہیں: build کے باہر ویجیٹس بنانا (فیکٹریز، کنسٹرکٹرز میں)

اکثر پوچھے گئے سوالات

Flutter میں BuildContext کیا ہے؟

BuildContext — ایک انٹرفیس ہے جو ایلیمنٹس کے درخت میں ویجیٹ کی پوزیشن کو ظاہر کرتا ہے۔ اس کے ذریعے ویجیٹ کو ماحول تک رسائی ملتی ہے: تھیم، میڈیا کوریز، نیویگیٹر اور InheritedWidget سے ڈیٹا۔ ہر ویجیٹ کا اپنا منفرد سیاق و سباق ہوتا ہے۔

BuildContext کیسے کام کرتا ہے؟

BuildContext درخت کو موجودہ ایلیمنٹ سے جڑ کی طرف اوپر گھومتا ہے، درخواست کردہ قسم کا قریب ترین InheritedWidget تلاش کرتا ہے۔ dependOnInheritedWidgetOfExactType طریقہ نہ صرف ڈیٹا تلاش کرتا ہے بلکہ ویجیٹ کو ان کی تبدیلیوں پر سبسکرائب بھی کرتا ہے — InheritedWidget کی تجدید پر ویجیٹ خود بخود دوبارہ تعمیر ہو جاتا ہے۔

BuildContext کو کلاس کے فیلڈز میں کیوں محفوظ نہیں کرنا چاہیے؟

BuildContext منسلک ہوتا ہے درخت میں ایلیمنٹ سے، اور ایلیمنٹ ختم ہو سکتا ہے (ویجیٹ ہٹائے جانے پر)۔ ویجیٹ ہٹانے کے بعد محفوظ کردہ سیاق و سباق کا استعمال مستثنیٰ کا باعث بنتا ہے۔ اگر غیر متوقع کال بیک میں سیاق و سباق درکار ہے — استعمال سے پہلے mounted چیک کریں۔

BuildContext اور Element میں کیا فرق ہے؟

BuildContext — انٹرفیس ہے، Element — نفاذ۔ ڈویلپر BuildContext کے ذریعے کام کرتا ہے، ایلیمنٹ کی مخصوص قسم کو جانے بغیر۔ Element Flutter کا داخلی طریقہ کار ہے، جو Widget کو RenderObject سے جوڑتا ہے اور لائف سائیکل کا انتظام کرتا ہے۔

کیا کسی دوسرے ویجیٹ کا BuildContext حاصل کیا جا سکتا ہے؟

کسی دوسرے ویجیٹ کے سیاق و سباق تک براہ راست رسائی ممکن نہیں۔ والدین کے سیاق و سباق کے لیے State کے لیے context.findAncestorStateOfType یا کلید (GlobalKey) استعمال کریں۔ بچے کے لیے — کال بیک منتقل کریں۔ BuildContext درجہ بندی سے باہر باہمی ویجیٹ رسائی کے لیے نہیں بنایا گیا ہے۔

خلاصہ

  • BuildContext — Flutter میں ایک بنیادی آبجیکٹ ہے جو ویجیٹ کی درخت میں پوزیشن کو ظاہر کرتا ہے اور InheritedWidget کے ذریعے درجہ بندی کے ماحول تک رسائی فراہم کرتا ہے
  • تلاش کا طریقہ کار — BuildContext درخت کو نیچے سے اوپر گھومتا ہے، درخواست کردہ قسم کا قریب ترین InheritedWidget تلاش کرتا ہے اور اس کی تبدیلیوں پر سبسکرائب ہوتا ہے
  • بنیادی استعمال — Theme.of(context), MediaQuery.of(context), Navigator.of(context) تھیمز، ریسپانسیویٹی اور نیویگیشن تک رسائی کے لیے
  • BuildContext بمقابلہ Element — BuildContext عوامی انٹرفیس ہے، Element نجی نفاذ ہے۔ ڈویلپر ہمیشہ BuildContext کے ذریعے کام کرتا ہے
  • لائف سائیکل — BuildContext زندہ ہے جب تک متعلقہ ایلیمنٹ زندہ ہے؛ dispose کے بعد سیاق و سباق استعمال نہیں کیا جانا چاہیے
  • غلطیاں — دیرپا آبجیکٹس میں سیاق و سباق محفوظ کرنا، initState میں استعمال، dispose کے بعد استعمال — بگس کے عام ذرائع
  • اصول — BuildContext کو صرف build/didChangeDependencies کے اندر استعمال کریں، اسے محفوظ نہ کریں، غیر متوقع منظرناموں میں mounted چیک کریں

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں