State Flutter میں ڈیٹا مینجمنٹ کا مرکزی آبجیکٹ ہے، جو StatefulWidget سے منسلک ہے اور تبدیل پذیر معلومات کو ذخیرہ کرنے اور انٹرفیس بنانے کا ذمہ دار ہے۔ سرکاری Flutter دستاویزات (Flutter.dev, 2026) کے مطابق، State ویجٹ کی پوری زندگی کے دوران موجود رہتا ہے اور اس کی تعمیر نو سے بچ جاتا ہے، UI اپ ڈیٹس کے درمیان ڈیٹا کی مستقل مزاجی کو یقینی بناتا ہے۔ خود ویجٹ کے برعکس، State اپنی فیلڈز کو تبدیل کر سکتا ہے اور setState کال کے ذریعے تعمیر نو شروع کر سکتا ہے۔
اہم نکات
State Flutter آرکیٹیکچر میں ایک آبجیکٹ ہے جو StatefulWidget کے تبدیل پذیر ڈیٹا کو ذخیرہ کرتا ہے اور یہ طے کرتا ہے کہ یہ ڈیٹا انٹرفیس میں کیسے ظاہر ہوتا ہے۔ ہر StatefulWidget، جب درخت میں داخل ہوتا ہے، createState طریقہ کے ذریعے بالکل ایک State آبجیکٹ بناتا ہے۔ State ویجٹ سے آزادانہ طور پر موجود رہتا ہے: اگر پیرنٹ نئے پیرامیٹرز کے ساتھ StatefulWidget کی تعمیر نو کرتا ہے، State وہی رہتا ہے اور widget پراپرٹی کے ذریعے اپ ڈیٹ شدہ ویجٹ حاصل کرتا ہے۔
Flutter آرکیٹیکچرل جائزہ (Google, 2026) کے مطابق، Widget اور State کی علیحدگی ایک دانستہ آرکیٹیکچرل فیصلہ ہے جو فریم ورک کو درخت کے عناصر کو دوبارہ استعمال کرنے کی اجازت دیتا ہے۔ ویجٹ (ایک ہلکی پھلکی تفصیل) کئی بار بنایا اور تباہ کیا جا سکتا ہے، لیکن State (ڈیٹا کے ساتھ ایک بھاری آبجیکٹ) میموری میں اس وقت تک رہتا ہے جب تک عنصر درخت میں ہے۔ یہ پیرنٹ ویجٹس کی بار بار تعمیر نو کے دوران ڈیٹا کے نقصان کو روکتا ہے۔
State StatefulWidget انٹرفیس کو جنیرکس کے ذریعے لاگو کرتا ہے: class _MyState extends State<MyWidget>۔ جنیرک State کو ایک مخصوص StatefulWidget قسم سے جوڑتا ہے، جو widget پراپرٹی کے ذریعے اس کی فیلڈز تک ٹائپ محفوظ رسائی فراہم کرتا ہے۔
State آبجیکٹ StatefulElement میں ذخیرہ ہوتا ہے — Widget اور RenderObject کے درمیان ایک درمیانی پرت۔ StatefulElement createState کے ذریعے State بناتا ہے، اس کا حوالہ رکھتا ہے، اور State کو مالک کے طور پر منتقل کرتا ہے۔ Element صرف اس وقت تباہ ہوتا ہے جب ویجٹ درخت سے ہٹا دیا جاتا ہے — اس وقت تک، State میموری میں رہتا ہے۔
State کی زندگی کا دور تعینیاتی ہے اور کالوں کی ایک سخت ترتیب پر مشتمل ہے۔ اس ترتیب کو سمجھنا صحیح وسائل کے انتظام اور میموری لیک کو روکنے کی بنیاد ہے۔
initState State بننے پر سب سے پہلے کال کیا جاتا ہے۔ اس طریقہ میں، کنٹرولرز، سٹریم سبسکرپشنز، ٹائمرز اور فیلڈز کی ابتدائی اقدار شروع کی جاتی ہیں۔ پہلی قطار میں super.initState() کال کرنا لازمی ہے۔ initState مرحلے میں، ویجٹ کا درخت ابھی پوری طرح منسلک نہیں ہوتا، اس لیے MediaQuery.of(context) جیسے طریقے صحیح طریقے سے کام نہیں کر سکتے۔
didChangeDependencies initState کے بعد اور InheritedWidget انحصار میں ہر تبدیلی پر کال کیا جاتا ہے۔ MediaQuery.of(context) یا Theme.of(context) initState میں نہیں بلکہ یہاں کال کرنا چاہیے، کیونکہ اس وقت تک درخت پہلے ہی منسلک ہو چکا ہوتا ہے۔ یہ طریقہ اس وقت بھی کال کیا جاتا ہے جب ویجٹ کسی مختلف سیاق و سباق میں جاتا ہے جہاں InheritedWidget مختلف اقدار فراہم کرتا ہے۔
build State کا اہم طریقہ ہے جو ویجٹ کا درخت لوٹاتا ہے۔ یہ initState کے بعد، didChangeDependencies کے بعد اور ہر setState کے بعد کال کیا جاتا ہے۔ build طریقہ کے کوئی ضمنی اثرات نہیں ہونے چاہئیں — یہ صرف موجودہ State فیلڈ اقدار کی بنیاد پر انٹرفیس بیان کرتا ہے۔
didUpdateWidget اس وقت کال کیا جاتا ہے جب پیرنٹ نئے پیرامیٹرز کے ساتھ StatefulWidget کی تعمیر نو کرتا ہے۔ State پرانے ویجٹ تک oldWidget کے ذریعے رسائی حاصل کرتا ہے اور اس کا نئے سے موازنہ کر سکتا ہے۔ اگر پیرامیٹرز تبدیل ہو گئے ہیں، تو حالت کو اپ ڈیٹ کیا جا سکتا ہے، نیا ڈیٹا لوڈ کیا جا سکتا ہے، یا اینیمیشن دوبارہ شروع کی جا سکتی ہے۔
dispose آخری طریقہ ہے جہاں تمام وسائل جاری کیے جاتے ہیں: کنٹرولرز، سبسکرپشنز، ٹائمرز۔ dispose کے بعد، State کو مردہ نشان زد کیا جاتا ہے: mounted false لوٹاتا ہے، setState کال کرنے سے استثناء پیدا ہوتا ہے۔ طریقہ کی آخری قطار میں super.dispose() کال کرنا لازمی ہے۔
| طریقہ | کب کال کیا جاتا ہے | لازمی super |
|---|---|---|
| initState | State بننے پر | ہاں، پہلی قطار میں |
| didChangeDependencies | initState کے بعد اور InheritedWidget تبدیل ہونے پر | ہاں |
| build | initState، didChangeDependencies، setState کے بعد | نہیں |
| didUpdateWidget | پیرنٹ سے نیا ویجٹ آنے پر | ہاں |
| setState | ڈویلپر کال کرنے پر | نہیں |
| dispose | درخت سے ہٹانے پر | ہاں، آخری قطار میں |
State کا کام کرنے کا طریقہ کار تین اہم اصولوں پر مبنی ہے: Element کے ساتھ وابستگی، setState کے ذریعے رد عمل، اور widget پراپرٹی کے ذریعے پیرنٹ تک رسائی۔ جب Flutter عناصر کا درخت بناتا ہے اور StatefulElement کا سامنا کرتا ہے، تو یہ منسلک ویجٹ کا createState کال کرتا ہے۔ بنایا گیا State عنصر میں ذخیرہ ہوتا ہے اور اس وقت تک موجود رہتا ہے جب تک عنصر ہٹا نہیں دیا جاتا۔
جب setState کال کیا جاتا ہے، State خود کو گندا نشان زد کرتا ہے اور اگلے فریم کے لیے تعمیر نو طے کرتا ہے۔ اہم: setState فوری طور پر build کال نہیں کرتا — یہ صرف تعمیر نو کی ضرورت کو رجسٹر کرتا ہے۔ Flutter موجودہ فریم میں تمام گندے عناصر کو جمع کرتا ہے اور انہیں بیچ میں دوبارہ بناتا ہے، جو کارکردگی کو بہتر بناتا ہے۔ build کال کرنے کے بعد، State صاف حالت میں واپس آ جاتا ہے۔
widget پراپرٹی State کو StatefulWidget کنسٹرکٹر میں دیے گئے پیرامیٹرز پڑھنے کی اجازت دیتی ہے۔ چونکہ StatefulWidget ناقابل تبدیلی ہے (StatelessWidget کی طرح)، اس کی فیلڈز تبدیل نہیں ہوتیں — جب پیرامیٹرز تبدیل ہوتے ہیں، پیرنٹ ایک نیا ویجٹ بناتا ہے، اور State اسے didUpdateWidget کے ذریعے حاصل کرتا ہے۔ یہ یقینی بناتا ہے کہ State ہمیشہ موجودہ پیرنٹ ڈیٹا کے ساتھ کام کرتا ہے۔
ٹائمر کے ذریعے تبدیل کردہ فیلڈ کے ساتھ بنیادی State مثال۔ initState، setState اور dispose کو ظاہر کرتی ہے:
class _TimerWidgetState extends State<TimerWidget> {
int _seconds = 0;
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(
const Duration(seconds: 1),
(_) => setState(() => _seconds++),
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text('$_seconds seconds elapsed');
}
}
پیرنٹ پیرامیٹرز تک رسائی اور didUpdateWidget کے ذریعے ان میں تبدیلیوں پر ردعمل کے لیے widget پراپرٹی استعمال کرنے کی مثال:
class _GreetingState extends State<GreetingWidget> {
String _displayName = '';
@override
void initState() {
super.initState();
_displayName = _formatName(widget.name);
}
@override
void didUpdateWidget(GreetingWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.name != oldWidget.name) {
setState(() {
_displayName = _formatName(widget.name);
});
}
}
String _formatName(String name) => name.trim().isEmpty ? 'Guest' : name;
@override
Widget build(BuildContext context) {
return Text('Hello, $_displayName!');
}
}
دوسری مثال میں، State انپٹ پیرامیٹر name میں تبدیلیوں کو ٹریک کرتا ہے اور صرف حقیقی تبدیلی ہونے پر ڈسپلے کو دوبارہ فارمیٹ کرتا ہے۔ widget.name != oldWidget.name کی جانچ کے بغیر، طریقہ ہر پیرنٹ تعمیر نو پر کال ہوتا، چاہے نام تبدیل نہ ہوا ہو — فریم ورک کے لیے غیر ضروری کام۔
State اور StatefulWidget Flutter آرکیٹیکچر میں دو مختلف کلاسز ہیں جو مختلف کردار ادا کرتی ہیں۔ StatefulWidget ایک ہلکا ناقابل تبدیلی ریپر ہے جو ویجٹ کنفیگریشن بیان کرتا ہے اور State بناتا ہے۔ State ایک بھاری آبجیکٹ ہے جو تبدیل پذیر ڈیٹا ذخیرہ کرتا ہے، سبسکرپشنز کا انتظام کرتا ہے اور UI بناتا ہے۔ یہ علیحدگی Flutter کو حالت کھوئے بغیر ویجٹس کو تباہ اور بنانے کی اجازت دیتی ہے۔
StatefulWidget کی تمام فیلڈز final ہونی چاہئیں اور کنسٹرکٹر میں سیٹ ہونی چاہئیں — یہ بننے کے بعد تبدیل نہیں ہوتیں۔ State، دوسری طرف، کسی بھی وقت اپنی فیلڈز تبدیل کر سکتا ہے، لیکن تمام تبدیلیوں سے پہلے setState کال ہونا چاہیے تاکہ Flutter کو تعمیر نو کی ضرورت کے بارے میں پتہ چلے۔ یہ اہم فرق ہے: StatefulWidget “kya dikhana hai” ہے، State “kyā dikhānā hai aur kaunā sā Data istemāl karnā hai” ہے۔
Flutter سورس کوڈ تجزیہ (Flutter SDK, 2026) کے مطابق، StatefulWidget میں صرف ایک لازمی فیلڈ ہے — createState، جبکہ State کے پاس BuildContext تک رسائی ہے، سٹریمز کی سبسکرائب کر سکتا ہے، اینیمیشنز اور کنٹرولرز کا انتظام کر سکتا ہے۔ یہ سفارش کی جاتی ہے کہ StatefulWidget کو ممکنہ حد تک سادہ رکھا جائے، تمام منطق کو State میں منتقل کیا جائے۔
Widget اور State کی علیحدگی ایک آرکیٹیکچرل فیصلہ ہے جو کنفیگریشن کی ناقابل تبدیلی کو یقینی بناتا ہے۔ اگر StatefulWidget خود حالت ذخیرہ کرتا، تو ہر پیرنٹ تعمیر نو پر حالت کھو جاتی۔ حالت کو الگ آبجیکٹ میں منتقل کرکے، Flutter یقینی بناتا ہے کہ ڈیٹا تعمیر نو سے بچ جاتا ہے، جبکہ ویجٹس ہلکے اور موازنہ کے قابل رہتے ہیں۔
State آبجیکٹ الگ تھلگ ہے — اس کی دوسرے ویجٹس کے State تک براہ راست رسائی نہیں ہے۔ ویجٹس کے درمیان ڈیٹا کے تبادلے کے لیے InheritedWidget یا بیرونی اسٹیٹ مینجمنٹ ٹولز استعمال ہوتے ہیں: Provider، Riverpod، Bloc، Redux۔ ہر طریقہ مسئلہ کو مختلف طریقے سے حل کرتا ہے: InheritedWidget ویجٹ درخت کے ذریعے کام کرتا ہے، Provider DI کنٹینر کے ذریعے، Bloc واقعہ سٹریمز کے ذریعے۔
ٹول کا انتخاب پروجیکٹ کے پیمانے پر منحصر ہے۔ چھوٹی ایپلیکیشن کے لیے، InheritedWidget اور مقامی State کافی ہیں۔ درمیانے اور بڑے پروجیکٹس کے لیے، Riverpod یا Bloc تجویز کیے جاتے ہیں — یہ جانچ کی اہلیت، پیش گوئی اور UI سے منطق کی علیحدگی کو یقینی بناتے ہیں۔ State پھر صرف مقامی ویجٹ ڈیٹا (فوکس، اسکرول، اینیمیشن) کے لیے استعمال ہوتا ہے۔
Flutter کمیونٹی سروے 2025 (Flutter Foundation، دسمبر 2025) کے مطابق، Riverpod نئے پروجیکٹس میں سب سے مقبول اسٹیٹ مینجمنٹ حل ہے (38%)، اس کے بعد Bloc (31%) اور Provider (22%) ہیں۔ تینوں ٹولز State کے ساتھ مطابقت رکھتے ہیں اور معیاری زندگی کے دور کو ترک کرنے کی ضرورت نہیں ہے۔
پہلی غلطی غیر متزامن کال بیک میں setState سے پہلے mounted چیک کرنا بھولنا ہے۔ جب ویجٹ درخت سے ہٹا دیا جاتا ہے (مثال کے طور پر، صارف اسکرین سے چلا گیا)، لیکن غیر متزامن آپریشن (HTTP درخواست) ابھی چل رہا ہے، اس کے مکمل ہونے کے بعد State پہلے ہی مردہ ہوتا ہے۔ مردہ State میں setState کال کرنے سے استثناء پیدا ہوتا ہے۔ چیک if (mounted) setState(...) مسئلہ حل کرتا ہے۔
دوسری غلطی didChangeDependencies کی بجائے initState میں InheritedWidget انحصار شروع کرنا ہے۔ initState میں، سیاق و سباق ابھی منسلک نہیں ہوتا، اس لیے MediaQuery.of(context) استثناء پیدا کرے گا۔ تمام InheritedWidget انحصار didChangeDependencies یا build میں سیٹ کرنے چاہئیں۔
تیسری غلطی setState کال کیے بغیر فیلڈز کو تبدیل کرنا ہے۔ اگر ڈویلپر setState کے بغیر State فیلڈ تبدیل کرتا ہے، Flutter کو تبدیلی کے بارے میں پتہ نہیں چلے گا اور UI اپ ڈیٹ نہیں ہوگا۔ مثال کے طور پر: بعد کے setState((){}) کے بغیر _list.add(item) فہرست کو تبدیل کرے گا، لیکن اسکرین وہی رہے گی۔
State میں غیر متزامن آپریشنز کے لیے حفاظتی نمونہ:
Future<void> _fetchData() async {
final data = await ApiService.fetch();
if (mounted) {
setState(() => _data = data);
}
}
mounted کی جانچ اس بات کو یقینی بناتی ہے کہ setState صرف زندہ State پر کال کیا جائے، “setState called after dispose” استثناء کو روکتا ہے۔
اکثر پوچھے گئے سوالات
StatefulWidget ایک ناقابل تبدیلی ویجٹ کنفیگریشن ہے، جبکہ State ایک قابل تبدیلی آبجیکٹ ہے جو ڈیٹا ذخیرہ کرتا ہے اور زندگی کے دور کا انتظام کرتا ہے۔ ویجٹ کو دوبارہ بنایا جا سکتا ہے، State کو نہیں۔ StatefulWidget createState کے ذریعے State بناتا ہے۔
بالکل ایک۔ createState طریقہ ایک بار کال کیا جاتا ہے جب StatefulWidget پہلی بار درخت میں داخل ہوتا ہے۔ چاہے پیرنٹ کئی بار تعمیر نو کرے، State آبجیکٹ وہی رہتا ہے جب تک ویجٹ کی قسم یا Key تبدیل نہ ہو۔
mounted ایک بولین جھنڈا ہے جو ظاہر کرتا ہے کہ State ویجٹ درخت میں ہے یا نہیں۔ dispose کال کرنے کے بعد، mounted false ہو جاتا ہے۔ استثناء سے بچنے کے لیے غیر متزامن کال بیکس میں setState سے پہلے جانچ کے لیے استعمال ہوتا ہے۔
نہیں۔ State ہمیشہ جنیرکس کے ذریعے مخصوص StatefulWidget سے منسلک ہوتا ہے: State<T extends StatefulWidget>۔ ویجٹ کے ساتھ تعلق کے بغیر براہ راست State بنانا آرکیٹیکچرل طور پر ناممکن ہے۔
ایک استثناء پیدا ہوتا ہے: “setState called after dispose”۔ dispose کے بعد، State مردہ سمجھا جاتا ہے، اور setState کے ذریعے UI کو دوبارہ بنانے کی کوئی بھی کوشش ممنوع ہے۔ حل ہر setState سے پہلے mounted چیک کرنا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں