Widget Tree Flutter میں ویجیٹس کا ایک درجہ بندی کا ڈھانچہ ہے جو صارف انٹرفیس کی ترتیب کو متعین کرتا ہے۔ انٹرفیس کا ہر عنصر، ایک بٹن سے لے کر پوری اسکرین تک، ایک علیحدہ ویجیٹ کے ذریعے پیش کیا جاتا ہے جو پیرنٹ کنٹینر کے اندر نیسٹڈ ہوتا ہے۔ Flutter ہر حالت کی تبدیلی پر Widget Tree کو اپ ڈیٹ کرتا ہے — فریم ورک نئے اور پرانے درخت کا موازنہ کرتا ہے اور کم سے کم تبدیلیاں لاگو کرتا ہے۔ Flutter Team, 2025 کے مطابق، ایک موثر درخت کا ڈھانچہ براہ راست اینیمیشن کی ہمواری اور انٹرفیس کی ردعمل کو متاثر کرتا ہے۔
اہم نکات
Widget Tree Flutter میں صارف انٹرفیس کی ایک اعلانیہ وضاحت ہے، جو نیسٹڈ ویجیٹس کے درخت کے طور پر بنائی گئی ہے۔ ہر ویجیٹ UI کا ایک حصہ متعین کرتا ہے: اس کی کنفیگریشن، ڈسپلے پیرامیٹرز اور تعامل پر رویہ۔ ڈویلپر بیان کرتا ہے کہ موجودہ ایپلیکیشن حالت میں انٹرفیس کیسا دکھنا چاہیے، اور Flutter اس وضاحت کو اسکرین پر پکسلز میں تبدیل کرنے کا کام کرتا ہے۔
لازمی فریم ورکس کے برعکس جہاں ڈویلپر براہ راست انٹرفیس عناصر میں ہیرا پھیری کرتا ہے، Flutter اعلانیہ نقطہ نظر استعمال کرتا ہے۔ جب ایپلیکیشن کی حالت بدلتی ہے، ایک نیا Widget Tree بنایا جاتا ہے، اور فریم ورک پرانے اور نئے درخت کے درمیان فرق کا حساب لگاتا ہے۔ یہ رینڈرنگ آپریشنز کی تعداد کو کم کرتا ہے اور کوڈ کو زیادہ پیش قیاس بناتا ہے۔
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Widget Tree")),
body: Center(
child: Column(
children: [
Text("ہیلو، Flutter"),
ElevatedButton(
onPressed: () {},
child: Text("مجھے دبائیں"),
),
],
),
),
),
);
}
}
اس مثال میں، Widget Tree MaterialApp، Scaffold، AppBar، Center، Column، Text اور ElevatedButton پر مشتمل ہے۔ ان میں سے ہر ویجیٹ درخت میں ایک نوڈ ہے۔ جب ایپلیکیشن کی حالت بدلتی ہے، Flutter build طریقہ کو دوبارہ کال کرتا ہے اور نتیجہ کا پچھلے درخت سے موازنہ کرتا ہے۔
Widget Tree ایک جڑ ویجیٹ سے شروع ہوتا ہے جو runApp طریقہ میں پاس کیا جاتا ہے۔ جڑ ویجیٹ عام طور پر MaterialApp، CupertinoApp یا WidgetsApp ہوتا ہے — یہ ایپلیکیشن کی عالمی ترتیبات متعین کرتا ہے۔ جڑ سے، درخت ذیلی ویجیٹس میں شاخیں ڈالتا ہے، جن میں سے ہر ایک اپنی اولاد پر مشتمل ہو سکتا ہے۔
Flutter میں ویجیٹس واحد بچہ (child پیرامیٹر کے ذریعے ایک بچہ قبول کرتے ہیں) اور متعدد بچے (children کے ذریعے بچوں کی فہرست قبول کرتے ہیں) میں تقسیم ہوتے ہیں۔ واحد بچہ کی مثالیں: Center، Padding، SizedBox، Container۔ متعدد بچے: Column، Row، Stack، ListView، GridView۔ یہ فرق Widget Tree کی ساخت کو متاثر کرتا ہے: متعدد بچوں والے ویجیٹس وسیع درخت بناتے ہیں، جبکہ واحد بچہ والے گہرے درخت بناتے ہیں۔
BuildContext Widget Tree میں ایک ویجیٹ کا مقام ہے۔ ہر ویجیٹ کا اپنا BuildContext ہوتا ہے، جو build طریقہ میں پاس کیا جاتا ہے اور پیرنٹ ویجیٹس، تھیم، MediaQuery اور دیگر InheritedWidgets تک رسائی کے لیے استعمال ہوتا ہے۔ BuildContext ویجیٹ اور Element Tree میں اس کے عنصر کے درمیان ایک پل کا کام کرتا ہے۔
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
return Container(
color: theme.colorScheme.primary,
child: Text(
"اسکرین کی چوڑائی: ${mediaQuery.size.width}"
),
);
}
}
اس مثال میں، BuildContext تھیم اور اسکرین کے طول و عرض حاصل کرنے کے لیے استعمال ہوتا ہے۔ Flutter Widget Tree میں اوپر جاتا ہے قریبی Theme اور MediaQuery تک، جو InheritedWidgets ہیں۔ یہ ظاہر کرتا ہے کہ کس طرح سیاق و سباق ویجیٹ کو درجہ بندی میں اس کی پوزیشن سے جوڑتا ہے۔
جب Flutter ایپلیکیشن شروع ہوتی ہے، runApp فنکشن کال کیا جاتا ہے، جو جڑ ویجیٹ لیتا ہے اور Widget Tree بنانا شروع کرتا ہے۔ عمل میں تین مراحل شامل ہیں: ویجیٹ کنفیگریشن بنانا، Element Tree تشکیل دینا اور حقیقی رینڈرنگ کے لیے RenderObject Tree بنانا۔
runApp فنکشن WidgetsFlutterBinding کے ذریعے ایک جڑ عنصر بناتا ہے، جو فریم ورک کو گرافکس انجن سے جوڑتا ہے۔ جڑ ویجیٹ کو درخت میں رکھا جاتا ہے، اور Flutter build طریقہ کو کال کرتا ہے تاکہ اسے ذیلی ویجیٹس سے بھر سکے۔ ہر build کال Widget Tree کا ایک نیا ذیلی گراف بناتی ہے۔
Widget Tree بنانے کے بعد، Flutter ایک ابتدائی لے آؤٹ انجام دیتا ہے — تمام ویجیٹس کے سائز اور مقامات کا حساب لگاتا ہے۔ یہ عمل جڑ سے شروع ہوتا ہے اور درخت میں نیچے کی طرف پھیلتا ہے۔ ہر ویجیٹ اپنے پیرنٹ سے پابندیاں وصول کرتا ہے اور ایک حسابی سائز واپس کرتا ہے۔ اگر سائز مماثل نہیں ہوتے، Flutter لے آؤٹ کی خرابی پیدا کرتا ہے۔
لے آؤٹ مکمل ہونے کے بعد، Flutter ہر ویجیٹ کو رینڈر کرنے کے لیے آگے بڑھتا ہے۔ RenderObject انٹرفیس کی وضاحت کو گرافکس کمانڈز میں تبدیل کرتا ہے جو GPU Skia یا Impeller کے ذریعے انجام دیتا ہے۔ پورا عمل — Widget Tree سے پکسلز تک — ہر حالت کی تبدیلی پر 120 فریم فی سیکنڈ تک دہرایا جاتا ہے۔
StatelessWidget ایک ویجیٹ ہے جس میں اندرونی قابل تبدیلی حالت نہیں ہوتی۔ اس کی ظاہری شکل مکمل طور پر کنسٹرکٹر کے ذریعے پاس کردہ ان پٹ پیرامیٹرز سے متعین ہوتی ہے۔ اگر پیرامیٹرز تبدیل نہیں ہوئے، StatelessWidget دوبارہ تعمیر نہیں ہوتا۔ یہ اسے کارکردگی کے لحاظ سے ہلکا بناتا ہے۔
جامد انٹرفیس عناصر — آئیکنز، ٹیکسٹ لیبلز، آرائشی تقسیم کار اور سادہ بٹن جن میں اندرونی منطق نہیں — کے لیے StatelessWidget استعمال کریں۔ Flutter دستاویزات کے مطابق، ایک عام ایپلیکیشن میں تقریباً 70% ویجیٹس StatelessWidget ہو سکتے ہیں، جو کوڑا کرکٹ جمع کرنے والے پر بوجھ کم کرتا ہے اور ری بلڈ کو تیز کرتا ہے۔
StatefulWidget ایک State آبجیکٹ بناتا ہے جو ویجیٹ کی دوبارہ تعمیر کے درمیان برقرار رہتا ہے۔ جب حالت بدلتی ہے (setState کے ذریعے)، Flutter ویجیٹ کو “گندا” کے طور پر نشان زد کرتا ہے اور اگلے فریم پر اسے دوبارہ بناتا ہے۔ StatefulWidget انٹرایکٹو عناصر کو قابل بناتا ہے: ان پٹ فیلڈز، اینیمیشنز، ٹائمرز اور متحرک فہرستیں۔
class CounterWidget extends StatefulWidget {
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("گنتی: $_count"),
ElevatedButton(
onPressed: () {
setState(() => _count++);
},
child: Text("اضافہ"),
),
],
);
}
}
اس مثال میں، StatefulWidget کاؤنٹر کو اپ ڈیٹ کرنے کے لیے setState استعمال کرتا ہے۔ جب حالت اپ ڈیٹ ہوتی ہے، Flutter Widget Tree کے صرف تبدیل شدہ حصے — CounterWidget اور اس کی اولاد — کو دوبارہ بناتا ہے۔ پیرنٹ ویجیٹس دوبارہ تعمیر نہیں ہوتے، جو Flutter کے اعلانیہ ماڈل کا ایک اہم فائدہ ہے۔
Widget Tree کنفیگریشن پرت ہے، جبکہ Element Tree ویجیٹس اور حقیقی رینڈرنگ کے درمیان درمیانی کڑی ہے۔ Widget Tree میں ہر ویجیٹ Element Tree میں ایک عنصر بناتا ہے، جو ویجیٹ کا حوالہ ذخیرہ کرتا ہے اور اس کے لائف سائیکل کا انتظام کرتا ہے۔ یہ آرکیٹیکچر Flutter کو تبدیلیوں کو مؤثر طریقے سے سنبھالنے کی اجازت دیتا ہے۔
جب Flutter پہلی بار کسی ویجیٹ کا سامنا کرتا ہے، یہ createElement طریقہ کال کرتا ہے، جو ایک متعلقہ عنصر بناتا ہے۔ StatelessWidget کے لیے، StatelessElement بنایا جاتا ہے؛ StatefulWidget کے لیے، StatefulElement بنایا جاتا ہے، جو ایک State آبجیکٹ بھی بناتا ہے۔ عنصر دوبارہ تعمیر کے چکروں کے درمیان برقرار رہتا ہے، چاہے ویجیٹ دوبارہ بنایا جائے۔
Key ایک شناخت کنندہ ہے جو Flutter کو پرانے اور نئے Widget Tree سے ویجیٹس کا ملاپ کرنے میں مدد دیتا ہے۔ اگر کسی ویجیٹ کے پاس Key ہے، Flutter اسے درخت میں اس کی پوزیشن کے بجائے متعلقہ عنصر تلاش کرنے کے لیے استعمال کرتا ہے۔ کنجیاں متحرک فہرستوں کے ساتھ کام کرتے وقت ضروری ہیں جہاں عناصر کی ترتیب بدل سکتی ہے۔
ListView(
children: items.map((item) => ListItem(
key: ValueKey(item.id),
data: item,
)).toList(),
)
Key کے بغیر، Flutter عناصر کو پوزیشن کے مطابق ملانا کرتا ہے، جو ترتیب بدلنے پر غلط حالت کے تحفظ کا سبب بن سکتا ہے۔ منفرد شناخت کنندہ کے ساتھ ValueKey اس بات کو یقینی بناتا ہے کہ ہر عنصر فہرست میں اپنی پوزیشن سے قطع نظر اپنی حالت برقرار رکھے۔
Widget Tree کی ساخت براہ راست Flutter ایپلیکیشن کی کارکردگی کو متاثر کرتی ہے۔ بہت سے نیسٹڈ ویجیٹس والے گہرے درختوں کو لے آؤٹ مرحلے کے لیے زیادہ وقت درکار ہوتا ہے اور میموری کے استعمال میں اضافہ ہوتا ہے۔ Flutter DevTools Widget Tree کا تجزیہ کرنے اور رکاوٹوں کی شناخت کرنے کے لیے اوزار فراہم کرتا ہے۔
نیسٹنگ کی ہر سطح لے آؤٹ اور پینٹ کے دوران اضافی حسابات کا اضافہ کرتی ہے۔ گہری زنجیر نیسٹنگ کے بجائے، چپٹی ساخت استعمال کریں۔ مثال کے طور پر، Expanded کے ساتھ Row، Align کے ساتھ متعدد نیسٹڈ Containers کی جگہ لے سکتا ہے۔ Flutter Team کے مطابق، درخت کی اصلاح لے آؤٹ کے وقت کو 40% تک کم کر سکتی ہے۔
Flutter DevTools “Widget Inspector” ٹول فراہم کرتا ہے، جو موجودہ Widget Tree کو حقیقی وقت میں دکھاتا ہے۔ ڈویلپر اسکرین پر کسی بھی ویجیٹ کو منتخب کر سکتا ہے اور درخت میں اس کا مقام، پیرامیٹرز اور لے آؤٹ پابندیاں دیکھ سکتا ہے۔ یہ غیر متوقع نیسٹنگ، ضرورت سے زیادہ ری بلڈ اور سائز کے مسائل کی شناخت میں مدد کرتا ہے۔
RepaintBoundary ایک ویجیٹ ہے جو آزاد رینڈرنگ کے لیے Widget Tree کے حصے کو الگ کرتا ہے۔ اگر RepaintBoundary کے اندر کا مواد بدل جائے، تو صرف اس کا علاقہ دوبارہ پینٹ ہوتا ہے، پوری اسکرین نہیں۔ اینیمیشنز، فہرستوں اور دیگر بار بار اپ ڈیٹ ہونے والے عناصر کے لیے RepaintBoundary استعمال کریں۔
RepaintBoundary(
child: CustomPaint(
painter: MyPainter(),
child: SizedBox(
width: 200,
height: 200,
),
),
)
اس مثال میں، RepaintBoundary CustomPaint کو علیحدہ رینڈرنگ علاقے میں الگ کرتا ہے۔ جب اس علاقے کے اندر اینیمیشن اپ ڈیٹ ہوتی ہے، صرف CustomPaint ویجیٹ دوبارہ پینٹ ہوتا ہے، جبکہ باقی اسکرین غیر تبدیل شدہ رہتی ہے۔ یہ متعدد اینی میٹڈ عناصر والے پیچیدہ انٹرفیس میں خاص طور پر مفید ہے۔
اکثر پوچھے گئے سوالات
Widget Tree ایک اعلانیہ انٹرفیس کی وضاحت ہے جو ہر ری بلڈ پر دوبارہ بنائی جاتی ہے۔ Element Tree اپ ڈیٹس کے درمیان برقرار رہتا ہے اور ویجیٹس کی حقیقی RenderObjects سے لائف سائیکل، حالت اور ملاپ کا انتظام کرتا ہے۔
ویجیٹس کی تعداد کی کوئی حد نہیں، لیکن عملی طور پر ہزاروں ویجیٹس والا درخت لے آؤٹ مرحلے کو سست کر سکتا ہے۔ Flutter کئی ہزار نوڈس تک کے درختوں کے لیے موزوں ہے؛ بڑی تعداد کے لیے، ListView.builder کے ذریعے ورچوئلائزیشن کی سفارش کی جاتی ہے۔
Flutter DevTools استعمال کریں — “Widget Inspector” ٹیب۔ ایپلیکیشن کو ڈیبگ موڈ میں چلائیں، براؤزر میں DevTools کھولیں، اور Widget Tree میں اس کا مقام دیکھنے کے لیے اسکرین پر کسی بھی ویجیٹ کو منتخب کریں۔
ری بلڈ حالت بدلنے پر ویجیٹ کنفیگریشن کو دوبارہ بنانے کا عمل ہے۔ Flutter تبدیل شدہ ویجیٹس کے لیے build طریقہ کو دوبارہ کال کرتا ہے، نئے Widget Tree کا پچھلے درخت سے موازنہ کرتا ہے اور Element Tree میں کم سے کم تبدیلیاں لاگو کرتا ہے۔
نیسٹنگ کی گہرائی کم کریں، جامد عناصر کے لیے const ویجیٹس استعمال کریں، اینیمیشنز کو الگ کرنے کے لیے RepaintBoundary لگائیں، اور جہاں StatelessWidget کافی ہو وہاں ضرورت سے زیادہ StatefulWidget سے بچیں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں