RenderObject Tree Flutter में पदानुक्रम का तीसरा स्तर है, जो स्क्रीन पर इंटरफ़ेस की वास्तविक रेंडरिंग के लिए ज़िम्मेदार है। इस ट्री का प्रत्येक नोड आकार गणना (layout) और ड्राइंग (painting) करता है, विजेट कॉन्फ़िगरेशन को पिक्सेल में बदलता है। Widget Tree के विपरीत, RenderObject Tree एक बार बनाया जाता है और केवल ज्यामिति या स्वरूप बदलने पर अपडेट होता है। Flutter API Reference, 2025 के अनुसार, RenderObject Tree की दक्षता सीधे एनिमेशन की स्मूथनेस और ऐप की प्रतिक्रिया गति निर्धारित करती है।
मुख्य बिंदु
RenderObject Tree — रेंडरिंग ऑब्जेक्ट्स की एक पदानुक्रमित संरचना है जो मेमोरी में इंटरफ़ेस का वास्तविक प्रतिनिधित्व है। प्रत्येक RenderObject अपने आकार, स्क्रीन पर स्थिति जानता है और स्वयं को बनाने में सक्षम है। विजेट के विपरीत, जो हल्के होते हैं और प्रति सेकंड सैकड़ों बार पुनः बनाए जा सकते हैं, RenderObject एक भारी ऑब्जेक्ट है जिसकी ग्राफ़िकल पाइपलाइन तक सीधी पहुँच है।
विजेट से पिक्सेल तक का रास्ता तीन चरणों से गुज़रता है: Widget Tree वर्णन करता है कि स्क्रीन पर क्या होना चाहिए; Element Tree जीवनचक्र प्रबंधित करता है; RenderObject Tree वास्तविक कार्य करता है। प्रत्येक RenderObjectWidget (जैसे Padding, Transform, CustomPaint) एक RenderObject बनाता है जो रेंडरिंग ट्री में जोड़ा जाता है। RenderBox — सबसे सामान्य प्रकार का RenderObject है, जो 99% मानक विजेट के लिए उपयोग होता है।
RenderObject — एक अमूर्त क्लास है जो layout और paint के लिए इंटरफ़ेस परिभाषित करता है। इसमें पैरेंट RenderObject और चाइल्ड ऑब्जेक्ट्स के संदर्भ होते हैं, साथ ही अमूर्त विधियाँ: performLayout, paint और hitTest। प्रत्येक विशिष्ट RenderObject इन विधियों को अपने व्यवहार के अनुसार लागू करता है: RenderFlex चाइल्ड एलिमेंट्स के बीच स्थान वितरित करता है, RenderImage छवि प्रदर्शित करता है, RenderParagraph टेक्स्ट आउटपुट करता है।
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
इस सरलीकृत संरचना में RenderObject में _needsLayout और _needsPaint फ़्लैग होते हैं जो ऑब्जेक्ट को अपडेट की आवश्यकता के रूप में चिह्नित करते हैं। जब Widget Tree बदलता है, Element Tree संबंधित RenderObject को layout या paint के लिए "गंदा" चिह्नित करता है, और अगले फ्रेम में Flutter केवल आवश्यक संचालन करता है।
प्रत्येक RenderObject दो मुख्य चरण करता है: layout (आकार और स्थिति निर्धारण) और paint (ड्राइंग)। ये चरण सख्त क्रम में निष्पादित होते हैं: पहले पूरे ट्री के लिए layout, फिर paint। यदि layout नहीं बदला है तो paint चरण छोड़ा जा सकता है, जिससे GPU संसाधन बचते हैं।
Layout के दौरान Flutter बाधाएँ (constraints) ऊपर से नीचे RenderObject Tree के माध्यम से भेजता है। प्रत्येक पैरेंट चाइल्ड ऑब्जेक्ट को न्यूनतम और अधिकतम चौड़ाई और ऊँचाई देता है। चाइल्ड ऑब्जेक्ट इन बाधाओं के भीतर अपना आकार गणना करता है और इसे पैरेंट को लौटाता है। इस प्रक्रिया को "downward pass" (बाधाओं को नीचे भेजना) और "upward pass" (आकार ऊपर भेजना) कहा जाता है।
Layout पूरा होने के बाद Flutter paint करता है — प्रत्येक RenderObject की ड्राइंग। पैरेंट PaintingContext बनाता है, इसे चाइल्ड ऑब्जेक्ट्स को भेजता है और ऑफ़सेट (offset) निर्दिष्ट करता है। प्रत्येक RenderObject Canvas पर ग्राफ़िकल प्रिमिटिव का उपयोग करके स्वयं बनाता है: आयत, वृत्त, टेक्स्ट, छवियाँ और ट्रांसफ़ॉर्मेशन। Canvas सीधे Skia या Impeller के साथ इंटरैक्ट करता है।
Flutter कार्य को न्यूनतम करने के लिए "गंदे" नोड्स तंत्र का उपयोग करता है। जब केवल एक RenderObject का आकार बदलता है, Flutter पूरे ट्री के layout की पुनर्गणना नहीं करता — वह बदले हुए नोड और उसके संभावित पूर्वजों को निकटतम निश्चित आकार वाले RenderBox तक चिह्नित करता है। इसी प्रकार, स्वरूप बदलने पर बिना पुनः layout के केवल paint चिह्नित होता है।
Flutter प्रदान करता है विभिन्न कार्यों के लिए RenderObject की कई श्रेणियाँ: मानक आयताकार एलिमेंट्स के लिए RenderBox, स्क्रॉल करने योग्य क्षेत्रों के लिए RenderSliver और CustomPainter के माध्यम से गैर-मानक रेंडरिंग के लिए कस्टम RenderObject। प्रत्येक प्रकार रेंडरिंग ट्री में अपनी भूमिका के लिए अनुकूलित है।
RenderBox — आयताकार इंटरफ़ेस एलिमेंट्स के लिए आधार क्लास। इसके उपप्रकार: RenderPadding (पैडिंग जोड़ता है), RenderTransform (ट्रांसफ़ॉर्मेशन लागू करता है), RenderFlex (Row और Column लागू करता है), RenderStack (एलिमेंट्स का ओवरले), RenderImage (छवि प्रदर्शन), RenderParagraph (टेक्स्ट प्रदर्शन)। प्रत्येक उपप्रकार अपने तर्क के लिए performLayout और paint को ओवरराइड करता है।
RenderSliver — स्क्रॉल करने योग्य क्षेत्रों के साथ काम करने के लिए RenderObject प्रकार है। RenderBox के विपरीत, Sliver SliverConstraints का उपयोग करता है जिसमें दृश्य क्षेत्र (viewport) की जानकारी शामिल होती है। RenderSliverList और RenderSliverGrid केवल दृश्य क्षेत्र में आने वाले एलिमेंट्स के लिए RenderObject बनाते हैं, जिससे लाखों रिकॉर्ड वाली सूचियों को संभाला जा सकता है।
गैर-मानक ग्राफ़िक्स के लिए CustomPaint और CustomPainter का उपयोग करें। CustomPaint RenderCustomPaint बनाता है जो CustomPainter की paint विधियों को कॉल करता है। यह Canvas पर पूर्ण नियंत्रण के साथ मनमानी आकृतियाँ, ग्राफ़ और एनिमेशन बनाने की अनुमति देता है। Flutter Team के अनुसार, CustomPainter जटिल वेक्टर ग्राफ़िक्स के लिए नेस्टेड मानक विजेट से अधिक कुशल है।
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
canvas.drawCircle(
Offset(size.width / 2, size.height / 2),
size.width / 3,
paint,
);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
इस उदाहरण में CirclePainter Canvas पर एक वृत्त बनाता है। shouldRepaint विधि केवल रंग बदलने पर true लौटाती है, जो अनावश्यक पुनः रेंडरिंग को रोकती है। CustomPainter को अधिकतम हल्का होना चाहिए — सभी भारी गणनाएँ paint विधियों के बाहर करें।
RenderObject Tree Element Tree से RenderObjectWidget तंत्र के माध्यम से बनता है। प्रत्येक RenderObjectWidget (Padding, Transform, CustomPaint) RenderObjectElement उत्पन्न करता है जो संबंधित RenderObject बनाता और प्रबंधित करता है। एलिमेंट मध्यस्थ की भूमिका निभाता है: वह विजेट से कॉन्फ़िगरेशन RenderObject को भेजता है और RenderObject को परिवर्तनों के बारे में सूचित करता है।
जब RenderObjectElement माउंट होता है, वह अपने विजेट की createRenderObject विधि कॉल करता है। विजेट RenderObject का इंस्टेंस बनाता है और इसे एलिमेंट को लौटाता है। एलिमेंट पैरेंट RenderObject की insertChildLayout विधि कॉल करके RenderObject को RenderObject Tree में शामिल करता है। यह प्रक्रिया केवल पहले माउंटिंग पर होती है — बाद के अपडेट में एलिमेंट केवल मौजूदा RenderObject के पैरामीटर अपडेट करता है।
जब विजेट की कॉन्फ़िगरेशन बदलती है (जैसे padding मान बदलता है), एलिमेंट updateRenderObject विधि कॉल करता है जो मौजूदा RenderObject को नई कॉन्फ़िगरेशन भेजता है। RenderObject स्वयं को layout या paint के लिए "गंदा" चिह्नित करता है, और अगले फ्रेम में फ्रेमवर्क आवश्यक अपडेट करता है।
एलिमेंट के अनमाउंट होने पर unmount विधि कॉल होती है जो RenderObject को RenderObject Tree से हटाती है और संसाधन मुक्त करती है। RenderObject.remove को पैरेंट से अलग करने के लिए कहा जाता है, जिसके बाद ऑब्जेक्ट गार्बेज कलेक्टर द्वारा एकत्र किया जा सकता है। Flutter गारंटी देता है कि कोई RenderObject संबंधित एलिमेंट के बिना ट्री में नहीं लटका रहता।
RepaintBoundary — एक विजेट है जो अपनी सामग्री की रेंडरिंग के लिए एक अलग स्तर बनाता है। जब RepaintBoundary की सामग्री बदलती है, केवल यह स्तर पुनः रेंडर होता है, स्क्रीन के अन्य भाग अपरिवर्तित रहते हैं। RepaintBoundary विशेष रूप से एनिमेशन, वीडियो प्लेयर, इंटरैक्टिव ग्राफ़ और अन्य बार-बार अपडेट होने वाले एलिमेंट्स के लिए उपयोगी है।
RepaintBoundary के मूल में RenderRepaintBoundary है — एक विशेष RenderObject जो अलग PictureLayer बनाता है। पहली रेंडरिंग पर RenderRepaintBoundary ग्राफ़िकल कमांड को इस स्तर में रिकॉर्ड करता है। बाद के अपडेट में, यदि केवल RepaintBoundary के अंदर की सामग्री बदली है, Flutter केवल इस स्तर को पुनः रेंडर करता है, पूरी स्क्रीन को नहीं। अन्य स्तर अपरिवर्तित रहते हैं और पुनः उपयोग होते हैं।
हर विजेट को RepaintBoundary की आवश्यकता नहीं है। इसका उपयोग करें जब इंटरफ़ेस का कोई भाग उच्च आवृत्ति (60 FPS या अधिक) पर अपडेट होता है और शेष स्क्रीन स्थिर है। सामान्य उदाहरण: एनिमेटेड लोडिंग इंडिकेटर, वीडियो प्लेयर, गेम Canvas, बार-बार पुनः रेंडरिंग वाला CustomPainter। स्थिर टेक्स्ट या बटन के लिए RepaintBoundary अनावश्यक है और केवल मेमोरी खपत बढ़ाता है।
| परिदृश्य | सुझाव | कारण |
|---|---|---|
| एनिमेशन | RepaintBoundary में लपेटें | बार-बार अपडेट होने वाले क्षेत्र को अलग करता है |
| स्क्रॉल सूची | आवश्यक नहीं | ListView स्वचालित रूप से स्तरों का उपयोग करता है |
| स्थिर टेक्स्ट | आवश्यक नहीं | बार-बार पुनः रेंडरिंग नहीं |
| CustomPainter | अनुशंसित | ग्राफ़िक्स की बार-बार पुनः रेंडरिंग |
प्रदर्शन RenderObject Tree नोड्स की संख्या, ट्री की गहराई और पुनः रेंडरिंग आवृत्ति पर निर्भर करता है। Flutter DevTools टूल ("Rendering" टैब) वास्तविक समय में RenderObject Tree का विश्लेषण करने की अनुमति देता है: repaint की संख्या, layout और paint का समय, स्तरों की संख्या और उनके आकार। नियमित विश्लेषण बाधाओं की पहचान करने में मदद करता है।
Overdraw — वह स्थिति जब एक पिक्सेल प्रति फ्रेम कई बार खींचा जाता है। उदाहरण के लिए, जब पारदर्शी विजेट दूसरे पर ओवरले होता है, GPU दोनों स्तरों को खींचता है। अपारदर्शी एलिमेंट्स के लिए opaque फ़्लैग का उपयोग करें (decoration के बजाय रंग सहित Container) ताकि Flutter अदृश्य स्तरों को छोड़ दे। Flutter Team के अनुसार, overdraw कम करने से paint समय 30% तक घट सकता है।
प्रत्येक RepaintBoundary और कुछ विजेट (Opacity, ClipRRect, Transform) अलग स्तर (PictureLayer) बनाते हैं। बहुत अधिक स्तर कंपोज़िशन समय बढ़ाते हैं। ग्रुपिंग का उपयोग करें: अलग-अलग विजेट पर कई Opacity के बजाय एक Opacity कंटेनर पर लागू करें। प्रत्येक एलिमेंट पर ClipRRect के बजाय सामान्य कंटेनर पर ClipRRect का उपयोग करें।
जब विजेट const घोषित किया जाता है, Flutter जानता है कि इसकी कॉन्फ़िगरेशन नहीं बदलेगी और बिना पुनः निर्माण के संबंधित RenderObject का पुनः उपयोग कर सकता है। Const कंस्ट्रक्टर गार्बेज कलेक्टर पर भार कम करते हैं और पहले फ्रेम को तेज़ करते हैं। निश्चित पैरामीटर वाले विजेट के लिए const का उपयोग करें: आइकन, शीर्षक, सजावटी एलिमेंट।
const Text("शीर्षक", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
अक्सर पूछे जाने वाले प्रश्न
Widget Tree — इंटरफ़ेस की हल्की कॉन्फ़िगरेशन है जो प्रत्येक rebuild पर पुनः बनाई जाती है। RenderObject Tree — रेंडरिंग ऑब्जेक्ट्स का भारी ट्री है जो संरक्षित रहता है और केवल ज्यामिति या स्वरूप बदलने पर अपडेट होता है।
Flutter DevTools का उपयोग करें — "Rendering" टैब। आप रेंडरिंग स्तर, layout और paint का समय, साथ ही प्रत्येक RenderObject के बारे में विस्तृत जानकारी देखेंगे: आकार, constraints, अपडेट आवश्यकता के फ़्लैग।
Dirty — वह RenderObject जो अपडेट की आवश्यकता के रूप में चिह्नित है। _needsLayout या _needsPaint फ़्लैग कॉन्फ़िगरेशन बदलने पर सेट होता है, और Flutter अगले फ्रेम में इस नोड के लिए layout या paint करता है।
हाँ, RenderBox का उपवर्ग बनाएँ और performLayout तथा paint विधियों को ओवरराइड करें। कस्टम RenderObject को Widget Tree में शामिल करने के लिए RenderObjectWidget का उपयोग करें। यह गैर-मानक रेंडरिंग के लिए एक उन्नत तकनीक है।
RepaintBoundary RenderRepaintBoundary बनाता है जो RenderObject Tree के हिस्से को एक अलग स्तर में अलग करता है। सामग्री बदलने पर केवल यह स्तर पुनः रेंडर होता है, ट्री का शेष भाग अपरिवर्तित रहता है।
निष्कर्ष
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें