InheritedWidget Flutter में एक विशेष विजेट है जो कंस्ट्रक्टर के माध्यम से स्पष्ट रूप से पास किए बिना विजेट ट्री में डेटा नीचे की ओर भेजता है। चाइल्ड विजेट BuildContext के माध्यम से डेटा तक पहुँचते हैं और स्वचालित रूप से अपडेट की सदस्यता लेते हैं। जब InheritedWidget में डेटा बदलता है, तो सभी आश्रित विजेट पुनर्निर्मित होते हैं। Flutter API Reference, 2025 के अनुसार, InheritedWidget Theme, MediaQuery, Localizations और अधिकांश स्थिति प्रबंधन लाइब्रेरीज़ की नींव है।
मुख्य बिंदु
InheritedWidget एक विजेट है जो अपने डेटा को Widget Tree में सभी वंशजों के लिए उपलब्ध कराता है। सामान्य विजेट के विपरीत जो केवल कंस्ट्रक्टर के माध्यम से चाइल्ड एलिमेंट्स को डेटा भेजता है, InheritedWidget सबट्री में किसी भी विजेट को पैरामीटर की श्रृंखला के बिना डेटा तक पहुँचने की अनुमति देता है। यह “prop drilling” समस्या को हल करता है — कई मध्यवर्ती विजेट्स के माध्यम से डेटा पास करना जो स्वयं इस डेटा का उपयोग नहीं करते।
Flutter में कई अंतर्निर्मित InheritedWidget शामिल हैं: Theme (रंग योजना और शैलियाँ), MediaQuery (स्क्रीन आकार, ओरिएंटेशन, पिक्सेल घनत्व), Localizations (स्थानीयकृत स्ट्रिंग्स), Directionality (पाठ दिशा), DefaultTextStyle (डिफ़ॉल्ट पाठ शैली)। ये विजेट MaterialApp जैसे रूट विजेट द्वारा सेट किए जाते हैं और पूरे एप्लिकेशन में उपलब्ध होते हैं।
InheritedWidget की अपनी कोई स्थिति नहीं होती — यह कंस्ट्रक्टर के माध्यम से पास किए गए डेटा को संग्रहीत करता है। जब InheritedWidget का पैरेंट नए डेटा के साथ पुनर्निर्मित होता है, तो पुराने और नए डेटा की तुलना करने के लिए updateShouldNotify विधि को कॉल किया जाता है। यदि विधि true लौटाती है, तो सभी आश्रित विजेट पुनर्निर्माण के लिए चिह्नित किए जाते हैं। यह एक सरल लेकिन प्रभावी रिएक्टिव अपडेट तंत्र है।
InheritedWidget के माध्यम से डेटा पास करने का तंत्र Element Tree पर आधारित है। जब कोई विजेट dependOnInheritedWidgetOfExactType को कॉल करता है, तो संबंधित एलिमेंट InheritedElement पर निर्भरता पंजीकृत करता है। जब InheritedWidget बदलता है, तो InheritedElement सभी आश्रित एलिमेंट्स को सूचित करता है, जो अगले फ्रेम में पुनर्निर्मित होते हैं।
dependOnInheritedWidgetOfExactType विधि केवल ट्री में InheritedWidget ढूंढ़ती नहीं है — यह वर्तमान एलिमेंट को सूचनाओं की सदस्यता देती है। यदि आप dependOn के बजाय findAncestorWidgetOfExactType का उपयोग करते, तो विजेट को डेटा मिल जाता लेकिन वह बदलने पर पुनर्निर्मित नहीं होता। यह एक महत्वपूर्ण अंतर है: dependOn एक सदस्यता है, findAncestor एक बार की खोज है।
जब कोई विजेट InheritedWidget का अनुरोध करता है, तो Flutter वर्तमान एलिमेंट से जड़ तक Element Tree में ऊपर जाता है, प्रकार मिलान के लिए प्रत्येक InheritedElement की जाँच करता है। पहला मिलता InheritedElement लौटाया जाता है। इसका मतलब है कि ट्री में निकटतम InheritedWidget की प्राथमिकता है — आप InheritedWidget को वंशजों के करीब रखकर किसी विशिष्ट स्तर पर डेटा को ओवरराइड कर सकते हैं।
class ThemeData {
final Color primaryColor;
final TextTheme textTheme;
const ThemeData({required this.primaryColor, required this.textTheme});
}
class MyTheme extends InheritedWidget {
final ThemeData data;
const MyTheme({required this.data, required Widget child}) : super(child: child);
static MyTheme of(BuildContext context) {
final widget = context.dependOnInheritedWidgetOfExactType<MyTheme>();
assert(widget != null, "MyTheme not found in tree");
return widget!;
}
@override
bool updateShouldNotify(MyTheme oldWidget) => oldWidget.data != data;
}
इस उदाहरण में, MyTheme वंशजों को डेटा प्रदान करने के लिए स्थैतिक of विधि का उपयोग करता है। dependOnInheritedWidgetOfExactType विधि एक निर्भरता पंजीकृत करती है, और updateShouldNotify यह निर्धारित करने के लिए पुराने और नए डेटा की तुलना करती है कि क्या आश्रित विजेट को पुनर्निर्मित करने की आवश्यकता है।
कस्टम InheritedWidget बनाने में दो चरण शामिल हैं: InheritedWidget का विस्तार करने वाली क्लास को परिभाषित करना, और वंशजों से पहुँच के लिए एक स्थैतिक of विधि को लागू करना। डेटा कंस्ट्रक्टर के माध्यम से पास किया जाता है, और updateShouldNotify विधि यह निर्धारित करती है कि आश्रित विजेट को कब पुनर्निर्मित होना चाहिए।
क्लास को InheritedWidget का विस्तार करना चाहिए और अनिवार्य child पैरामीटर के साथ कंस्ट्रक्टर के माध्यम से डेटा स्वीकार करना चाहिए। डेटा किसी भी प्रकार का हो सकता है: प्रिमिटिव, ऑब्जेक्ट, फ़ंक्शन। मुख्य नियम यह है कि डेटा अपरिवर्तनीय (immutable) होना चाहिए ताकि पुराने और नए मानों की विश्वसनीय रूप से तुलना की जा सके।
स्थैतिक of विधि BuildContext लेती है और InheritedWidget डेटा लौटाती है। अंदर, यह dependOnInheritedWidgetOfExactType को कॉल करती है, जो ट्री में निर्दिष्ट प्रकार का निकटतम InheritedWidget ढूंढ़ती है। यदि InheritedWidget नहीं मिलता है, तो विधि कार्यान्वयन के आधार पर एक अपवाद फेंकती है या डिफ़ॉल्ट मान लौटाती है।
डेटा तक पहुँचने के लिए, विजेट build विधि के अंदर MyWidget.of(context) को कॉल करता है। Flutter स्वचालित रूप से विजेट को अपडेट की सदस्यता देता है। यदि डेटा बदलता है, तो विजेट अगले फ्रेम में पुनर्निर्मित होता है। यह अनावश्यक पैरामीटर के बिना स्वच्छ और घोषणात्मक कोड की अनुमति देता है।
class UserPreferences extends InheritedWidget {
final String languageCode;
final bool darkMode;
const UserPreferences({
required this.languageCode,
required this.darkMode,
required Widget child,
}) : super(child: child);
static UserPreferences of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<UserPreferences>()!;
}
@override
bool updateShouldNotify(UserPreferences oldWidget) =>
oldWidget.languageCode != languageCode || oldWidget.darkMode != darkMode;
}
इस उदाहरण में, UserPreferences उपयोगकर्ता सेटिंग्स संग्रहीत करता है। updateShouldNotify विधि प्रत्येक फ़ील्ड की अलग-अलग तुलना करती है, जो केवल एक पैरामीटर बदलने पर अनावश्यक पुनर्निर्माण को रोकता है। कई फ़ील्ड वाले अपने स्वयं के InheritedWidget के लिए समान दृष्टिकोण का उपयोग करें।
updateShouldNotify InheritedWidget की मुख्य विधि है जो यह निर्धारित करती है कि क्या आश्रित विजेट को डेटा परिवर्तनों के बारे में सूचित करने की आवश्यकता है। यदि विधि false लौटाती है, तो आश्रित विजेट पुनर्निर्मित नहीं होते, भले ही InheritedWidget को समान डेटा के साथ एक नया इंस्टेंस प्राप्त हुआ हो। यह प्रदर्शन के लिए अत्यंत महत्वपूर्ण है।
केवल उन फ़ील्ड की तुलना करें जो वास्तव में बदले हैं और प्रदर्शन को प्रभावित करते हैं। यदि InheritedWidget में 10 फ़ील्ड हैं लेकिन केवल एक UI को प्रभावित करता है, तो केवल उस फ़ील्ड की जाँच करें। संग्रह के लिए, गहरी तुलना या अपरिवर्तनीय डेटा संरचनाओं का उपयोग करें। List या Map के लिए == का उपयोग न करें, क्योंकि वे संदर्भ द्वारा तुलना करते हैं।
सबसे आम गलती बिना तुलना के true लौटाना है। इसके कारण सभी आश्रित विजेट हर पैरेंट अपडेट पर पुनर्निर्मित होते हैं, भले ही डेटा न बदला हो। दूसरी गलती डेटा बदलने पर false लौटाना है, जिससे पुराना UI हो जाता है। तीसरी जटिल तुलना है जो हर फ्रेम चलती है और काम धीमा करती है।
InheritedWidget और कॉलबैक (कंस्ट्रक्टर के माध्यम से फ़ंक्शन पास करना) अलग-अलग समस्याओं को हल करते हैं। InheritedWidget उस डेटा के लिए उपयुक्त है जिसकी ट्री के विभिन्न स्तरों पर कई विजेट को आवश्यकता होती है। कॉलबैक पैरेंट से किसी विशिष्ट चाइल्ड तक या इसके विपरीत एकतरफ़ा ईवेंट पास करने के लिए सुविधाजनक हैं। चुनाव एप्लिकेशन आर्किटेक्चर और अपडेट आवृत्ति पर निर्भर करता है।
InheritedWidget का उपयोग करें जब डेटा की आवश्यकता विभिन्न नेस्टिंग स्तरों पर कई विजेट को हो: ऐप थीम, उपयोगकर्ता सेटिंग्स, डिवाइस जानकारी, वर्तमान सत्र डेटा। InheritedWidget विशेष रूप से “वैश्विक” डेटा के लिए प्रभावी है जो शायद ही कभी बदलता है लेकिन UI के विभिन्न भागों में आवश्यक होता है।
कॉलबैक (कॉलबैक फ़ंक्शन) चाइल्ड विजेट से पैरेंट तक ईवेंट पास करने के लिए उपयुक्त हैं: बटन दबाना, सूची आइटम चयन, फ़ॉर्म सबमिशन। कॉलबैक स्पष्ट रूप से इंगित करते हैं कि चाइल्ड क्या कार्य कर सकता है और छिपी निर्भरताएँ नहीं बनाते। थोड़ी संख्या में स्तरों पर ट्री में डेटा नीचे भेजने के लिए, कंस्ट्रक्टर पैरामीटर का उपयोग करना भी सरल है।
| मानदंड | InheritedWidget | कॉलबैक |
|---|---|---|
| दिशा | ऊपर से नीचे (पैरेंट → वंशज) | नीचे से ऊपर (चाइल्ड → पैरेंट) या सीधा |
| दायरा | पूरी सबट्री | विशिष्ट विजेट |
| पुनर्निर्माण | डेटा बदलने पर स्वचालित | मैन्युअल setState आवश्यक |
| जटिलता | मध्यम (InheritedWidget क्लास चाहिए) | कम (बस एक फ़ंक्शन) |
Provider और Riverpod InheritedWidget के ऊपर बनाई गई Flutter में लोकप्रिय स्थिति प्रबंधन लाइब्रेरीज़ हैं। वे इसकी क्षमताओं का विस्तार करते हैं: ChangeNotifier समर्थन, अनमाउंट पर स्वचालित निपटान, आलसी आरंभीकरण, और जेनेरिक के साथ सरलीकृत सिंटैक्स जोड़ते हैं।
Provider किसी भी प्रकार की वस्तु को ट्री में नीचे भेजने के लिए InheritedWidget का उपयोग करता है। ChangeNotifierProvider ChangeNotifier के माध्यम से परिवर्तनों को ट्रैक करता है और notifyListeners कॉल करने पर updateShouldNotify को कॉल करता है। यह डेवलपर को मैन्युअल रूप से InheritedWidget बनाने और updateShouldNotify लागू करने से मुक्त करता है।
सीधा InheritedWidget अधिक नियंत्रण देता है और बाहरी निर्भरताओं की आवश्यकता नहीं होती। Provider तैयार बुनियादी ढाँचा प्रदान करता है: Consumer, Selector, MultiProvider, ProxyProvider। चुनाव एप्लिकेशन जटिलता पर निर्भर करता है। सरल प्रोजेक्ट के लिए, सीधा InheritedWidget पर्याप्त है; बड़े प्रोजेक्ट के लिए, Provider या Riverpod बॉयलरप्लेट कोड कम करते हैं।
// प्रत्यक्ष InheritedWidget
class UserProvider extends InheritedWidget {
final UserData userData;
const UserProvider({required this.userData, required Widget child}) : super(child: child);
static UserData of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<UserProvider>()!.userData;
@override
bool updateShouldNotify(UserProvider old) => old.userData != userData;
}
// Provider समतुल्य
return ChangeNotifierProvider<UserData>(
create: (_) => UserData(),
child: MyApp(),
);
उदाहरण में दोनों दृष्टिकोण एक ही समस्या हल करते हैं — UserData को ट्री में नीचे भेजना। Provider कोड की मात्रा कम करता है लेकिन InheritedWidget की कार्यप्रणाली को छिपाता है। सीधा InheritedWidget पूर्ण नियंत्रण और समझ देता है कि क्या हो रहा है, जो Flutter सीखने और जटिल पुनर्निर्माण समस्याओं को डीबग करने में विशेष रूप से महत्वपूर्ण है।
अक्सर पूछे जाने वाले प्रश्न
InheritedWidget BuildContext के माध्यम से सभी वंशजों के लिए डेटा उपलब्ध कराता है, जबकि सामान्य विजेट केवल कंस्ट्रक्टर के माध्यम से डेटा भेजता है। InheritedWidget वंशजों को डेटा अपडेट की सदस्यता भी देता है।
आश्रित विजेट केवल तभी पुनर्निर्मित होते हैं जब updateShouldNotify true लौटाता है। यदि विधि सही ढंग से लागू की गई है, तो पुनर्निर्माण केवल तब होता है जब डेटा वास्तव में बदलता है, हर पैरेंट पुनर्निर्माण पर नहीं।
हाँ, आप एक ही ट्री में किसी भी संख्या में InheritedWidget का उपयोग कर सकते हैं। प्रत्येक एक विशिष्ट प्रकार का डेटा प्रदान करता है, और विजेट एक साथ कई InheritedWidget से डेटा प्राप्त कर सकते हैं।
dependOn विजेट को अपडेट की सदस्यता देता है — जब डेटा बदलता है, तो विजेट पुनर्निर्मित होता है। findAncestor बिना सदस्यता के एक बार की खोज करता है, और विजेट को डेटा परिवर्तनों के बारे में पता नहीं चलेगा।
सरल स्थिति (थीम, सेटिंग्स) के लिए InheritedWidget पर्याप्त है। व्यावसायिक तर्क वाली जटिल स्थिति के लिए, Provider, Riverpod या BLoC का उपयोग करें — वे InheritedWidget पर बनाए गए हैं और आवश्यक बुनियादी ढाँचा जोड़ते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें