StatefulWidget एक Flutter विजेट है जिसमें परिवर्तनीय स्थिति होती है, जो UI को उपयोगकर्ता क्रियाओं, एसिंक्रोनस घटनाओं और डेटा स्ट्रीम पर प्रतिक्रिया करने की अनुमति देता है। आधिकारिक Flutter दस्तावेज़ीकरण (Flutter.dev, 2026) के अनुसार, StatefulWidget का उपयोग एप्लिकेशन के सभी इंटरैक्टिव तत्वों के लिए किया जाता है: इनपुट फ़ॉर्म, एनिमेशन, चेकबॉक्स, स्विच और स्क्रीन जो नेटवर्क से डेटा लोड करते हैं। StatelessWidget के विपरीत, यह एक अलग State ऑब्जेक्ट बनाता है जो अपने पूरे जीवनचक्र में बना रहता है और विजेट को पुनः बनाए बिना पुनर्निर्मित किया जा सकता है।
मुख्य बातें
StatefulWidget एक Flutter क्लास है जो उपयोगकर्ता क्रियाओं, सिस्टम इवेंट या एसिंक्रोनस संचालनों के जवाब में अपनी स्थिति बदल सकता है। StatelessWidget के विपरीत, StatefulWidget सीधे रेंडर नहीं होता — यह एक State ऑब्जेक्ट बनाता है जो रेंडरिंग को संभालता है। दो क्लासेज़ (Widget और State) में यह विभाजन Flutter को विजेट को पुनः बनाए बिना UI को पुनर्निर्मित करने की अनुमति देता है, जो बार-बार अपडेट के दौरान एक महत्वपूर्ण प्रदर्शन लाभ प्रदान करता है।
StatefulWidget की आर्किटेक्चर “परिवर्तनीय और अपरिवर्तनीय के पृथक्करण” पैटर्न का अनुसरण करती है: विजेट स्वयं अपरिवर्तनीय रहता है (StatelessWidget की तरह), जबकि सभी परिवर्तनीय स्थिति एक अलग State ऑब्जेक्ट में संग्रहीत की जाती है। यह Flutter को प्रकार और Key द्वारा उनकी तुलना करके विजेट का पुन: उपयोग करने की अनुमति देता है, साथ ही पुनर्निर्माणों के बीच वास्तविक स्थिति को संरक्षित करता है।
Google (Flutter Architectural Overview, 2026) के अनुसार, StatefulWidget उन परिदृश्यों के लिए इष्टतम है जहाँ विजेट के जीवनकाल में स्थिति एक से अधिक बार बदलती है: टेक्स्ट फ़ील्ड, एनिमेशन, टाइमर, डेटा स्ट्रीम, एसिंक्रोनस लोड। एक बार के आरंभीकरण के लिए, StatelessWidget पर्याप्त है।
StatefulWidget अनिवार्य है जब विजेट को बाहरी घटनाओं पर प्रतिक्रिया देनी हो: बटन क्लिक, HTTP अनुरोध पूर्णता, डेटाबेस डेटा अपडेट, WebSocket सब्सक्रिप्शन। यह एनिमेशन वाले विजेट, कंट्रोलर वाले टेक्स्ट फ़ील्ड और फ़ोकस प्रबंधित करने वाले घटकों के लिए भी आवश्यक है। यदि कोई विजेट केवल डेटा प्रदर्शित करता है और ईवेंट उत्पन्न नहीं करता है, तो StatelessWidget का उपयोग करें।
StatefulWidget दो क्लासेज़ से बना है: स्वयं StatefulWidget (हल्का, अपरिवर्तनीय) और State (भारी, परिवर्तनीय)। फ्रेमवर्क createState() विधि के माध्यम से State बनाता है, जिसे ट्री में सम्मिलित करने पर एक बार कॉल किया जाता है। State को widget गुण के माध्यम से विजेट का संदर्भ मिलता है और जीवनचक्र में किसी भी बिंदु पर इसके फ़ील्ड तक पहुँच सकता है।
जीवनचक्र StatefulWidget के छह मुख्य चरणों से बना है, जिनमें से प्रत्येक विशिष्ट कार्य करने के लिए एक ओवरराइड करने योग्य विधि प्रदान करता है। संसाधनों के उचित प्रबंधन और मेमोरी लीक से बचने के लिए इन चरणों को समझना महत्वपूर्ण है।
createState जीवनचक्र की पहली विधि है, जिसे StatefulWidget को ट्री में सम्मिलित करने पर कॉल किया जाता है। इसे इस विजेट से जुड़ा एक नया State इंस्टेंस लौटाना चाहिए। यह विधि तत्व के पूरे जीवनकाल में ठीक एक बार कॉल की जाती है। यहां भारी संचालन न करना महत्वपूर्ण है — createState जितना संभव हो उतना हल्का होना चाहिए।
initState State बनने के तुरंत बाद, पहले UI निर्माण से पहले कॉल किया जाता है। यहां किया जाता है: कंट्रोलरों का आरंभीकरण (TextEditingController, AnimationController), डेटा स्ट्रीम की सदस्यता (StreamSubscription), टाइमर सेटअप और फ़ील्ड का प्रारंभिक आरंभीकरण। Flutter दस्तावेज़ (Flutter.dev, 2026) के अनुसार, initState में BuildContext.of() को कॉल नहीं किया जा सकता — ट्री अभी पूरी तरह माउंट नहीं हुआ है।
didChangeDependencies initState के बाद और हर बार InheritedWidget निर्भरताएँ बदलने पर कॉल किया जाता है। यह MediaQuery.of(context) को कॉल करने या Theme की सदस्यता लेने के लिए उपयुक्त स्थान है — वे मान जो एप्लिकेशन के रनटाइम के दौरान बदल सकते हैं। यदि कोई विजेट InheritedWidget का उपयोग करता है, तो आरंभीकरण तर्क यहाँ होना चाहिए, initState में नहीं।
build मुख्य विधि है जो विजेट ट्री लौटाती है। इसे initState के बाद, didChangeDependencies के बाद और प्रत्येक setState के बाद कॉल किया जाता है। didUpdateWidget तब कॉल किया जाता है जब माता-पिता पुनर्निर्माण करते हैं और नए पैरामीटर के साथ StatefulWidget पास करते हैं। यहाँ पुराने और नए विजेट फ़ील्ड की तुलना की जा सकती है और यदि आवश्यक हो, तो स्थिति को अपडेट किया जा सकता है।
dispose जीवनचक्र का अंतिम चरण है। यहाँ सभी संसाधन मुक्त किए जाते हैं: स्ट्रीम से सदस्यता रद्द की जाती है, कंट्रोलर हटाए जाते हैं, टाइमर रद्द किए जाते हैं। dispose को कॉल न करने से मेमोरी लीक होती है। dispose के बाद, State को मृत माना जाता है — इसके अंदर setState कॉल करने से अपवाद उत्पन्न होता है।
StatefulWidget का कार्य तंत्र तीन संस्थाओं के समन्वित कार्य पर आधारित है: Widget (हल्का विवरण), Element (मध्यवर्ती परत) और State (डेटा भंडारण)। जब Flutter विवरण में StatefulWidget पाता है, तो यह StatefulElement बनाता है, जो createState को कॉल करता है और State ऑब्जेक्ट का संदर्भ संग्रहीत करता है। जब माता-पिता पुनर्निर्माण करते हैं, Flutter नए विजेट की वर्तमान Element से तुलना करता है — यदि प्रकार और Key मेल खाते हैं, तो Element अपडेट होता है और State वही रहता है।
स्थिति केवल setState कॉल के माध्यम से बदली जाती है, जो फ्रेमवर्क को पुनर्निर्माण की आवश्यकता के बारे में सूचित करता है। यह समझना महत्वपूर्ण है: setState स्वचालित रूप से स्थिति नहीं बदलता — यह केवल विजेट को “गंदा” के रूप में चिह्नित करता है। डेवलपर स्वतंत्र रूप से setState को पास किए गए कॉलबैक में State फ़ील्ड अपडेट करता है। कॉलबैक पूरा होने के बाद, Flutter build को कॉल करता है और UI अपडेट करता है।
Dart/Flutter टीम (Dart Language Specification, 2026) के अनुसार, यह पृथक्करण सुनिश्चित करता है कि build कॉल करने से पहले सभी स्थिति परिवर्तन समकालिक रूप से होते हैं, उस स्थिति को समाप्त करते हुए जहाँ UI आंशिक रूप से अपडेटेड डेटा प्रदर्शित करता है। यह Flutter में इंटरफ़ेस संगति का एक महत्वपूर्ण तंत्र है।
आइए एक सरल StatefulWidget देखें — एक बटन क्लिक काउंटर। यह मूल पैटर्न प्रदर्शित करता है: State बनाना, initState में फ़ील्ड आरंभ करना, setState के माध्यम से बदलना:
class CounterScreen extends StatefulWidget {
const CounterScreen({super.key});
@override
State<CounterScreen> createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $_count'),
ElevatedButton(
onPressed: _increment,
child: const Text('Increment'),
),
],
);
}
}
एसिंक्रोनस डेटा लोडिंग और जीवनचक्र प्रबंधन के साथ एक उदाहरण। StatefulWidget नेटवर्क से डेटा लोड करता है और लोडिंग स्थिति प्रदर्शित करता है:
class UserProfilePage extends StatefulWidget {
final String userId;
const UserProfilePage({super.key, required this.userId});
@override
State<UserProfilePage> createState() => _UserProfilePageState();
}
class _UserProfilePageState extends State<UserProfilePage> {
UserModel? _user;
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadUser();
}
Future<void> _loadUser() async {
final user = await UserService.fetchUser(widget.userId);
setState(() {
_user = user;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
if (_isLoading) return const CircularProgressIndicator();
return Text('Hello, ${_user!.name}');
}
}
दूसरे उदाहरण में, यह ध्यान रखना महत्वपूर्ण है: initState एक एसिंक्रोनस ऑपरेशन शुरू करता है, लेकिन विधि स्वयं एसिंक्रोनस नहीं है। एसिंक्रोनसी को एक अलग विधि _loadUser के अंदर async/await के माध्यम से कार्यान्वित किया जाता है, जो अनुरोध पूरा होने के बाद setState के माध्यम से स्थिति अपडेट करता है। यह दृष्टिकोण सुनिश्चित करता है कि डेटा प्राप्त होने से पहले विजेट लोडिंग संकेतक सही ढंग से प्रदर्शित करता है।
StatefulWidget और StatelessWidget के बीच चुनाव केवल स्थिति होने के बारे में नहीं है। StatefulWidget initState, didChangeDependencies, didUpdateWidget और dispose विधियों के साथ एक पूर्ण जीवनचक्र प्रदान करता है, जो कंट्रोलर, एनिमेशन और स्ट्रीम के साथ काम करने के लिए आवश्यक हैं। StatelessWidget, दूसरी ओर, इन विधियों को नहीं रखता है और फ्रेमवर्क के लिए हमेशा हल्का होता है।
Flutter टीम की अनुशंसा (Flutter docs, 2026) एप्लिकेशन में StatefulWidgets की संख्या को कम करना है, स्थिति को ट्री में ऊपर उठाकर (State Hoisting) या स्थिति प्रबंधन समाधान (Riverpod, Bloc, Provider) का उपयोग करके। प्रत्येक StatefulWidget एक State ऑब्जेक्ट बनाता है जो तत्व हटाए जाने तक जीवित रहता है — जितने अधिक ऐसे विजेट होंगे, मेमोरी लोड उतना ही अधिक होगा।
| मानदंड | StatefulWidget | StatelessWidget |
|---|---|---|
| स्थिति | परिवर्तनीय | अपरिवर्तनीय |
| जीवनचक्र | 6 चरण | केवल build |
| State ऑब्जेक्ट | अलग से बनाया जाता है | आवश्यक नहीं |
| setState | उपलब्ध | उपलब्ध नहीं |
| सदस्यता | initState/dispose | समर्थित नहीं |
| const कंस्ट्रक्टर | सीमित | पूरी तरह समर्थित |
| मेमोरी खपत | अधिक | कम |
StatefulWidget को State ऑब्जेक्ट बनाने और बनाए रखने की आवश्यकता के कारण StatelessWidget की तुलना में अधिक संसाधनों की आवश्यकता होती है। हालाँकि, StatefulWidget का सही उपयोग प्रदर्शन समस्याओं का कारण नहीं बनता यदि कुछ नियमों का पालन किया जाए। पहला, StatefulWidget की गहरी नेस्टिंग से बचें — प्रत्येक स्तर ट्री ट्रैवर्सल में ओवरहेड जोड़ता है। दूसरा, जटिल StatefulWidget को कई सरल विजेट में विभाजित करें, प्रत्येक अपनी स्थिति के अपने हिस्से के लिए जिम्मेदार है।
Flutter प्रदर्शन अनुसंधान (Flutter.dev, फरवरी 2026) के अनुसार, FPS गिरने का सबसे आम कारण माता-पिता विजेट में setState कॉल करना है जो सभी वंशजों का पुनर्निर्माण करता है, जिसमें StatelessWidgets शामिल हैं जिन्होंने अपना प्रदर्शन नहीं बदला है। समाधान UI के परिवर्तनीय भाग को एक अलग StatefulWidget में निकालना है ताकि setState केवल न्यूनतम आवश्यक विजेट का पुनर्निर्माण करे।
State के अंदर const का उपयोग करना एक और महत्वपूर्ण तकनीक है। यदि चाइल्ड विजेट को const के रूप में घोषित किया जाता है, तो Flutter माता-पिता में setState कॉल करने पर उनका पुनर्निर्माण नहीं करेगा। यह फ्रेमवर्क पर लोड कम करता है और फ्रेम रेंडरिंग समय घटाता है।
प्रत्येक setState कॉल पूर्ण विजेट पुनर्निर्माण शुरू करता है। यदि स्थिति उच्च आवृत्ति पर बदलती है (उदाहरण के लिए, एनिमेशन या डेटा स्ट्रीम), तो मैन्युअल रूप से setState कॉल करने के बजाय AnimatedBuilder, ValueListenableBuilder या StreamBuilder का उपयोग करने पर विचार करें। ये विजेट पुनर्निर्माण को अनुकूलित करते हैं, केवल UI के उस हिस्से को अपडेट करते हैं जो वास्तव में बदला है।
StatefulWidget के साथ पहली सामान्य गलती dispose के बाद setState कॉल करना है। जब कोई विजेट ट्री से हटा दिया जाता है, State को मृत माना जाता है, और कोई भी setState कॉल “setState called after dispose” अपवाद उत्पन्न करता है। यह अक्सर तब होता है जब विजेट हटाए जाने के बाद कोई एसिंक्रोनस ऑपरेशन पूरा होता है। समाधान setState कॉल करने से पहले mounted फ़्लैग की जाँच करना या dispose में एसिंक्रोनस ऑपरेशन रद्द करना है।
दूसरी गलती build विधि में भारी गणना करना है। चूँकि build प्रत्येक setState और प्रत्येक माता-पिता पुनर्निर्माण पर कॉल किया जाता है, सभी गणनाएँ जितनी संभव हो उतनी हल्की होनी चाहिए। यदि संसाधन-गहन ऑपरेशन की आवश्यकता है, तो इसे एक अलग Isolate में ले जाएँ या परिणाम को State फ़ील्ड में कैश करें।
तीसरी गलती super.initState() और super.dispose() को कॉल न करना है। इन विधियों को ओवरराइड करते समय, डेवलपर को माता-पिता के कार्यान्वयन को कॉल करना होगा। ऐसा न करने पर फ्रेमवर्क Element स्थिति को ठीक से प्रबंधित नहीं कर पाएगा, जिससे ट्रैक करने में मुश्किल बग हो सकते हैं।
mounted जाँचेंsuper.initState() और super.dispose() कॉल करना न भूलेंअक्सर पूछे जाने वाले प्रश्न
StatefulWidget setState के माध्यम से अपनी स्थिति बदल सकता है, इसका एक जीवनचक्र (initState, dispose) है और यह एक अलग State ऑब्जेक्ट बनाता है। StatelessWidget स्थिति नहीं बदल सकता और इसके पास जीवनचक्र विधियाँ नहीं हैं — यह केवल पास किए गए डेटा को प्रदर्शित करता है।
createState प्रत्येक StatefulElement इंस्टेंस के लिए ठीक एक बार कॉल किया जाता है। भले ही माता-पिता कई बार पुनर्निर्माण करें, जब तक विजेट का प्रकार और Key नहीं बदलते, createState कॉल नहीं किया जाता — मौजूदा State ऑब्जेक्ट का उपयोग किया जाता है।
संसाधन मुक्त नहीं होंगे: कंट्रोलर पृष्ठभूमि में काम करते रहेंगे, स्ट्रीम सब्सक्रिप्शन सक्रिय रहेंगे, टाइमर रद्द नहीं होंगे। इससे मेमोरी लीक होती है और dispose के बाद setState कॉल हो सकता है, जो अपवाद उत्पन्न करता है।
हाँ, StatefulWidget का कंस्ट्रक्टर const हो सकता है। हालाँकि, यह StatelessWidget जितना लाभ प्रदान नहीं करता — State ऑब्जेक्ट पहली बार सम्मिलित करने पर भी बनाया जाएगा। const केवल विजेट को ही प्रभावित करता है (हल्का रैपर), State को नहीं।
didUpdateWidget तब कॉल किया जाता है जब माता-पिता नए पैरामीटर के साथ StatefulWidget पास करते हैं। यह स्थिति को नए डेटा के साथ सिंक्रोनाइज़ करने के लिए आवश्यक है — उदाहरण के लिए, यदि पैरामीटर में userId बदल गया है, तो नए उपयोगकर्ता का प्रोफ़ाइल लोड करना होगा।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें