Widget Flutter फ्रेमवर्क की केंद्रीय अवधारणा है, जो यूज़र इंटरफ़ेस तत्व के कॉन्फ़िगरेशन का वर्णन करती है। बटन से लेकर जटिल एनिमेशन तक हर विज़ुअल घटक एक Widget है। अन्य फ्रेमवर्क के विपरीत, जहाँ UI को अलग XML फ़ाइलों में वर्णित किया जाता है या अनिवार्य रूप से चित्रित किया जाता है, Flutter Widget संरचना के माध्यम से इंटरफ़ेस बनाता है — छोटे अविभाज्य तत्वों को एक पदानुक्रमित ट्री में संयोजित करना। Flutter दस्तावेज़ीकरण (2025) के अनुसार, Flutter SDK लाइब्रेरी में Material Design, Cupertino और कस्टम शैलियों को कवर करने वाले 260 से अधिक अंतर्निर्मित Widget शामिल हैं।
मुख्य बातें
Flutter में Widget यूज़र इंटरफ़ेस के एक हिस्से का अपरिवर्तनीय (immutable) वर्णन है। प्रत्येक Widget में कॉन्फ़िगरेशन गुण होते हैं: आकार, रंग, स्थिति, टेक्स्ट, ईवेंट हैंडलर और चाइल्ड Widget। Widget स्वयं सीधे रेंडर नहीं होते — वे ब्लूप्रिंट हैं जिनके आधार पर Flutter Engine RenderObject बनाता है, जो स्क्रीन पर वास्तविक ग्राफ़िकल ऑब्जेक्ट है।
Flutter का दर्शन कहता है: “Everything is a Widget”। इसका मतलब है कि न केवल दृश्य तत्व (Text, Image, Button) Widget हैं, बल्कि संरचनात्मक ब्लॉक (Padding, Center, Column, Stack), व्यवहारिक ब्लॉक (GestureDetector, AnimatedBuilder) और यहाँ तक कि एप्लिकेशन स्वयं (MaterialApp, CupertinoApp) भी Widget हैं। यह दृष्टिकोण एकरूपता सुनिश्चित करता है: किसी भी स्क्रीन तत्व को सरल नेस्टिंग के माध्यम से किसी अन्य के साथ जोड़ा जा सकता है।
Google I/O 2024 — Flutter Widgets Deep Dive के अनुसार, Flutter पर औसत एप्लिकेशन में किसी भी समय 200 से 1500 Widget होते हैं। इस मात्रा के बावजूद, Flutter C++ Skia/Impeller इंजन स्तर पर अनुकूलन के कारण बजट उपकरणों पर भी 60 FPS बनाए रखता है। Widget हल्की वस्तुएँ हैं (प्रत्येक 40–80 बाइट्स), इसलिए उनका निर्माण प्रदर्शन की बाधा नहीं है।
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('नमस्ते, Flutter!'),
),
),
);
}
}
यह समझने के लिए कि Widget कैसे काम करता है, तीन परस्पर जुड़े ट्री से युक्त Flutter आर्किटेक्चर को समझना आवश्यक है। पहला — Widget ट्री — UI कॉन्फ़िगरेशन का वर्णन करता है। यह एक हल्का ट्री है जो प्रत्येक फ्रेम पर पूरी तरह से पुनर्निर्मित हो सकता है (गार्बेज कलेक्टर पुराने Widget को हटाता है और नए बनाता है)। Widget अपरिवर्तनीय (immutable) हैं: यदि टेक्स्ट का रंग बदलता है, तो नए रंग के साथ एक नया Text Widget बनाया जाता है, पुराना छोड़ दिया जाता है।
दूसरा ट्री — Element ट्री — Widget और RenderObject के बीच की कड़ी है। Element में Widget (कॉन्फ़िगरेशन) और RenderObject (रेंडरिंग) का संदर्भ होता है। जब Widget बदलता है, Flutter नए Widget की तुलना पुराने Element से करता है और निर्णय लेता है: मौजूदा RenderObject को अपडेट करें (यदि Widget उसी प्रकार का है) या नया बनाएँ (यदि Widget प्रकार बदल गया है)। इस प्रक्रिया को Reconciliation कहा जाता है और यह React Virtual DOM के समान है।
तीसरा ट्री — RenderObject ट्री — स्क्रीन पर वास्तविक रेंडरिंग के लिए ज़िम्मेदार है। RenderObject में विशिष्ट आकार, स्थितियाँ और पेंट विधियाँ होती हैं। Flutter Engine (C++ Skia या Impeller) RenderObject ट्री को ट्रैवर्स करता है और प्रत्येक नोड को रेंडर करता है। RenderObject ट्री सबसे भारी ट्री है, इसलिए Flutter उसी प्रकार के Widget पर स्विच करते समय RenderObject को पुनः उपयोग करके अपने परिवर्तनों को कम करता है।
| ट्री | उद्देश्य | अपरिवर्तनीय? | जीवनचक्र |
|---|---|---|---|
| Widget | UI कॉन्फ़िगरेशन (ब्लूप्रिंट) | हाँ | प्रत्येक build पर पुनर्निर्मित |
| Element | Widget ↔ RenderObject कड़ी | नहीं | तब तक मौजूद जब तक विजेट ट्री में है |
| RenderObject | रेंडरिंग और लेआउट | नहीं | भारी, जब संभव हो पुनः उपयोग किया जाता है |
Flutter Widget को दो मूल प्रकारों में विभाजित करता है: StatelessWidget और StatefulWidget। StatelessWidget एक ऐसा विजेट है जिसमें परिवर्तनीय स्थिति नहीं होती। StatelessWidget की उपस्थिति पूरी तरह से उसके कंस्ट्रक्टर द्वारा निर्धारित होती है और रेंडर करने के बाद बदल नहीं सकती। उदाहरण: Text, Icon, Divider, Padding। StatelessWidget के सभी गुण कंस्ट्रक्टर में final के रूप में घोषित किए जाते हैं और केवल पढ़ने योग्य होते हैं।
StatefulWidget परिवर्तनीय स्थिति वाला एक विजेट है। यह दो वर्गों से मिलकर बना है: Widget स्वयं (अपरिवर्तनीय कॉन्फ़िगरेशन, StatelessWidget की तरह) और State (परिवर्तनीय स्थिति)। Widget को State से अलग करना Flutter में एक प्रमुख आर्किटेक्चरल निर्णय है। Widget प्रत्येक build पर पुनर्निर्मित होता है, लेकिन State ऑब्जेक्ट ट्री में विजेट के पूरे जीवनचक्र में रहता है, अपनी स्थिति बनाए रखता है।
जब setState() कॉल किया जाता है, Flutter State को “गंदा” चिह्नित करता है और अगले फ्रेम में सबट्री को पुनर्निर्मित करने के लिए build() विधि कॉल करता है। महत्वपूर्ण: setState() Widget को पुनर्निर्मित नहीं करता — यह केवल मौजूदा State पर build() कॉल को ट्रिगर करता है। इसका मतलब है कि StatefulWidget चाइल्ड Widget की स्थिति खोए बिना UI को अपडेट कर सकता है, जब तक चाइल्ड तत्वों की कुंजियाँ (Key) स्थिर रहती हैं।
// StatelessWidget — उपस्थिति कभी नहीं बदलती
class GreetingWidget extends StatelessWidget {
const GreetingWidget({super.key, required this.name});
final String name;
@override
Widget build(BuildContext context) {
return Text('नमस्ते, $name');
}
}
// StatefulWidget — परिवर्तनीय स्थिति वाला काउंटर
class CounterWidget extends StatefulWidget {
const CounterWidget({super.key});
@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: const Text('बढ़ाएँ'),
),
],
);
}
}
Flutter में सभी Widget को कार्यात्मक उद्देश्य के अनुसार तीन मुख्य श्रेणियों में विभाजित किया जा सकता है। Layout Widget — स्क्रीन पर चाइल्ड तत्वों की स्थिति के लिए ज़िम्मेदार हैं। Row और Column बच्चों को एक पंक्ति में रखते हैं, Stack एक को दूसरे के ऊपर रखता है, Expanded और Flexible उपलब्ध स्थान वितरित करते हैं। Layout Widget का अपना कोई दृश्य प्रतिनिधित्व नहीं होता — वे चाइल्ड विजेट की स्थिति और आकार का प्रबंधन करते हैं।
Painting Widget — दृश्य शैली के लिए ज़िम्मेदार हैं। Container सजावट (रंग, ग्रेडिएंट, छाया, सीमा) को लेआउट गुणों के साथ जोड़ता है। Padding स्पेसिंग जोड़ता है, DecoratedBox पृष्ठभूमि खींचता है, Transform रूपांतरण (घूर्णन, स्केल) लागू करता है। Painting Widget दृश्य शैली के निर्माण खंड हैं और अक्सर वांछित उपस्थिति प्राप्त करने के लिए Layout Widget के साथ उपयोग किए जाते हैं।
Interactive Widget — उपयोगकर्ता इनपुट को संभालते हैं। GestureDetector इशारों (टैप, स्वाइप, पिंच) का पता लगाता है, InkWell Material रिपल इफ़ेक्ट जोड़ता है, TextField टेक्स्ट इनपुट स्वीकार करता है, Slider और Switch मानक नियंत्रण तत्व प्रदान करते हैं। Interactive Widget कॉलबैक फ़ंक्शन के माध्यम से ईवेंट उठाते हैं जो कंस्ट्रक्टर को पास किए जाते हैं या स्थिति प्रदाताओं के माध्यम से संभाले जाते हैं।
| श्रेणी | Widget उदाहरण | उद्देश्य |
|---|---|---|
| Layout | Row, Column, Stack, Expanded, Flexible, Align | चाइल्ड तत्वों की स्थिति और आकार |
| Painting | Container, Padding, DecoratedBox, RotatedBox | रंग, पृष्ठभूमि, सीमाएँ, छायाएँ, रूपांतरण |
| Interactive | GestureDetector, InkWell, TextField, Slider | स्पर्श, इनपुट, इशारों को संभालना |
| Platform | MaterialApp, CupertinoApp, Theme, MediaQuery | प्लेटफ़ॉर्म एकीकरण, थीम, अनुकूलन |
| Async | FutureBuilder, StreamBuilder, ValueListenableBuilder | एसिंक्रोनस डेटा से रिएक्टिव अपडेट |
Flutter Widget of the Week (Google, 2025) के अनुसार, Flutter समुदाय व्यावहारिक रूप से किसी भी इंटरफ़ेस को बनाने के लिए layout + painting + interactive Widget के संयोजन का सक्रिय रूप से उपयोग करता है। उदाहरण के लिए, एक बटन: InkWell (interactive) + Container (painting) + Text (static) + Padding (layout)। यह मॉड्यूलरिटी कोड दोहराव के बिना विभिन्न संदर्भों में मानक ब्लॉक का पुनः उपयोग करने की अनुमति देती है।
Widget संरचना — यह कुछ Widget को दूसरों के अंदर नेस्ट करके UI बनाने की प्रक्रिया है। शास्त्रीय विरासत (extends) के विपरीत, जहाँ चाइल्ड क्लास पेरेंट के व्यवहार को प्राप्त करती है, Flutter एकत्रीकरण का उपयोग करता है: प्रत्येक Widget में child पैरामीटर (एक के लिए) या children (कई के लिए) के माध्यम से अन्य Widget होते हैं। यह दृष्टिकोण अधिक लचीलापन और पुन: उपयोग प्रदान करता है।
BuildContext Widget के बाद दूसरी सबसे महत्वपूर्ण अवधारणा है। BuildContext तत्व ट्री में Widget की स्थिति का वर्णनकर्ता है। BuildContext के माध्यम से, Widget पूर्वज विजेट (Theme.of(context), MediaQuery.of(context), Navigator.of(context)) तक पहुँच सकता है। BuildContext build() विधि को पास किया जाता है और पेरेंट और चाइल्ड तत्वों के साथ बातचीत के लिए उपयोग किया जाता है। प्रत्येक Widget के पास बिल्कुल एक BuildContext होता है, जो ट्री में उसकी स्थिति को विशिष्ट रूप से पहचानता है।
Flutter Architectural Overview (Google, 2025) के अनुसार, BuildContext InheritedWidget का आधार है — एक तंत्र जो कंस्ट्रक्टर के माध्यम से स्पष्ट पासिंग के बिना ट्री में नीचे डेटा पास करने की अनुमति देता है। Theme, MediaQuery, Navigator और Provider अंदरूनी रूप से InheritedWidget का उपयोग करते हैं। कोई भी गहराई से नेस्टेड Widget BuildContext.dependOnInheritedWidgetOfExactType के माध्यम से पूर्वज डेटा तक पहुँच सकता है, जो BuildContext को Flutter की रिएक्टिव आर्किटेक्चर की कुंजी बनाता है।
// नेस्टिंग के माध्यम से Widget संरचना
Scaffold(
appBar: AppBar(title: const Text('मेरा ऐप')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Flutter में आपका स्वागत है',
style: TextStyle(fontSize: 24)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () { /* nav */ },
child: const Text('शुरू करें'),
),
],
),
),
)
// BuildContext के माध्यम से थीम तक पहुँच
Text(
'स्टाइल किया गया टेक्स्ट',
style: Theme.of(context).textTheme.headlineMedium,
)
पहली और सबसे आम गलती है जहाँ StatelessWidget पर्याप्त हो वहाँ StatefulWidget का उपयोग करना। कई शुरुआती Flutter डेवलपर सभी विजेट के लिए StatefulWidget बनाते हैं, भले ही स्थिति बाहरी प्रदाता (Provider, Riverpod, BLoC) में संग्रहीत हो। यह अत्यधिक है और प्रदर्शन को ख़राब करता है। नियम: StatelessWidget का उपयोग करें यदि स्थिति बाहरी रूप से प्रबंधित की जाती है या यदि विजेट की अपनी परिवर्तनीय स्थिति नहीं है।
दूसरी गलती — बिना const कंस्ट्रक्टर के build विधि के अंदर Widget बनाना। बिना const के बनाया गया प्रत्येक Widget प्रत्येक build पर पुनः आवंटित होता है। यदि आप build() के अंदर const कंस्ट्रक्टर के साथ Widget बनाते हैं, Flutter उसी इंस्टेंस का पुनः उपयोग कर सकता है, गार्बेज कलेक्टर पर भार कम करता है। जहाँ भी संभव हो const जोड़ें — विशेष रूप से Text, Icon, SizedBox, Padding और अन्य स्टेटलेस Widget के लिए।
तीसरी गलती — कुंजियों (Key) के साथ गलत काम करना। Flutter ट्री के पुनर्निर्माण करते समय Widget की पहचान करने के लिए Key का उपयोग करता है। यदि Widget की सूची बिना Key के पुनर्निर्मित की जाती है, Flutter तत्वों के क्रम को भ्रमित कर सकता है, जिससे गलत एनिमेशन या स्थिति हानि होती है। सूचियों में तत्वों के लिए हमेशा Key (जैसे ValueKey या ObjectKey) जोड़ें, विशेष रूप से गतिशील डेटा के साथ ListView.builder का उपयोग करते समय।
अक्सर पूछे जाने वाले प्रश्न
StatelessWidget — परिवर्तनीय स्थिति के बिना विजेट, इसकी उपस्थिति पूरी तरह से कंस्ट्रक्टर द्वारा निर्धारित होती है। StatefulWidget — परिवर्तनीय स्थिति वाला विजेट, जो एक अलग State ऑब्जेक्ट में संग्रहीत होती है और विजेट को पुनर्निर्मित किए बिना setState() के माध्यम से अपडेट की जा सकती है। जहाँ संभव हो StatelessWidget का उपयोग करें, StatefulWidget — जब स्थानीय स्थिति की आवश्यकता हो।
Widget की अपरिवर्तनीयता प्रदर्शन के लिए Flutter का आर्किटेक्चरल निर्णय है। यदि Widget परिवर्तनीय होते, Flutter प्रत्येक build पर पुराने और नए कॉन्फ़िगरेशन की सुरक्षित रूप से तुलना नहीं कर पाता। अपरिवर्तनीयता Flutter को शीघ्रता से यह निर्धारित करने की अनुमति देती है कि Widget बदला है या नहीं (== ऑपरेटर के माध्यम से) और मौजूदा RenderObject का पुनः उपयोग करती है, महँगी रेंडरिंग संचालन को कम करती है।
BuildContext तत्व ट्री में Widget की स्थिति का वर्णनकर्ता है। इसके माध्यम से, Widget पूर्वज विजेट (Theme, MediaQuery, Navigator) और InheritedWidget तक पहुँच प्राप्त करता है। BuildContext का उपयोग नेविगेशन (Navigator.of(context)), SnackBar दिखाने और Provider के साथ बातचीत के लिए भी किया जाता है। प्रत्येक Widget build() विधि के माध्यम से BuildContext प्राप्त करता है और इसे वंशजों को पास करता है।
तत्वों की क्षैतिज व्यवस्था के लिए Row, ऊर्ध्वाधर व्यवस्था के लिए Column, एक दूसरे के ऊपर तत्वों को रखने के लिए Stack का उपयोग करें। Row और Column flexbox सिद्धांत पर काम करते हैं: बच्चे mainAxisSize, mainAxisAlignment और crossAxisAlignment के अनुसार स्थान घेरते हैं। Stack किनारों या केंद्र के सापेक्ष सटीक स्थिति के लिए positioned बच्चों का उपयोग करता है।
Flutter तीन तंत्रों के माध्यम से उच्च प्रदर्शन प्राप्त करता है: (1) Widget सस्ते हैं — हल्की अपरिवर्तनीय वस्तुएँ (40–80 बाइट्स), उनका निर्माण GC पर भार नहीं डालता। (2) RenderObject पुन: उपयोग — उसी प्रकार के Widget पर स्विच करते समय RenderObject पुनः उपयोग होता है, महँगे पुनर्निर्माण से बचाता है। (3) Skia/Impeller इंजन — repaint boundaries के माध्यम से कम ड्रॉ कॉल के साथ C++ स्तर पर रेंडरिंग।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें