निर्माण विधि इस प्रकार है कि यह होना चाहिए में बनाया गया है शुद्ध / बिना किसी दुष्प्रभाव । ऐसा इसलिए है क्योंकि कई बाहरी कारक नए विजेट बिल्ड को ट्रिगर कर सकते हैं, जैसे:
- रूट पॉप / पुश
- स्क्रीन आकार, आमतौर पर कीबोर्ड उपस्थिति या अभिविन्यास परिवर्तन के कारण होता है
- पैरेंट विजेट ने अपने बच्चे को फिर से बनाया
- एक InheritedWidget विजेट (
Class.of(context)पैटर्न) परिवर्तन पर निर्भर करता है
इसका मतलब यह है कि buildविधि को http कॉल को ट्रिगर या किसी भी राज्य को संशोधित नहीं करना चाहिए ।
यह सवाल से कैसे संबंधित है?
आप जिस समस्या का सामना कर रहे हैं, वह यह है कि आपकी बिल्ड विधि के साइड-इफेक्ट्स हैं / शुद्ध नहीं है, जिससे बाहरी बिल्ड कॉल परेशान करती है।
बिल्ड कॉल को रोकने के बजाय, आपको अपनी बिल्ड विधि को शुद्ध बनाना चाहिए, ताकि इसे बिना किसी प्रभाव के कभी भी कॉल किया जा सके।
अपने उदाहरण के मामले में, आप में एक अपने विजेट को बदलने चाहते हैं StatefulWidgetतो करने के लिए जो HTTP कॉल निकालने initStateअपने की State:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<int> future;
@override
void initState() {
future = Future.value(42);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// create some layout here
},
);
}
}
यह मैं पहले से जानता हूं। मैं यहां आया क्योंकि मैं वास्तव में पुनर्वित्त का अनुकूलन करना चाहता हूं
अपने बच्चों को भी बनाने के लिए मजबूर किए बिना एक विजेट को फिर से बनाने में सक्षम बनाना संभव है।
जब एक विजेट का उदाहरण समान रहता है; स्पंदन उद्देश्यपूर्वक बच्चों का पुनर्निर्माण नहीं करेगा। तात्पर्य यह है कि आप अनावश्यक विजेट को रोकने के लिए अपने विजेट ट्री के कुछ हिस्सों को कैश कर सकते हैं।
सबसे आसान तरीका डार्ट constकंस्ट्रक्टरों का उपयोग करना है :
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
उस constकीवर्ड के लिए धन्यवाद , DecoratedBoxसैकड़ों बार कॉल किए जाने पर भी इसका उदाहरण समान रहेगा।
लेकिन आप मैन्युअल रूप से एक ही परिणाम प्राप्त कर सकते हैं:
@override
Widget build(BuildContext context) {
final subtree = MyWidget(
child: Text("Hello World")
);
return StreamBuilder<String>(
stream: stream,
initialData: "Foo",
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text(snapshot.data),
subtree,
],
);
},
);
}
इस उदाहरण में जब स्ट्रीमब्यूलर को नए मूल्यों के बारे में सूचित किया जाता है, subtreeभले ही स्ट्रीमब्यूलर / कॉलम न करें। ऐसा इसलिए होता है, क्योंकि बंद होने के लिए धन्यवाद, MyWidgetपरिवर्तन नहीं हुआ।
एनिमेशन में इस पैटर्न का बहुत उपयोग किया जाता है। विशिष्ट उपयोग हैं AnimatedBuilderऔर सभी संक्रमण जैसे कि AlignTransition।
आप subtreeअपनी कक्षा के एक क्षेत्र में भी स्टोर कर सकते हैं , हालांकि कम अनुशंसित है क्योंकि यह हॉट-रीलोड सुविधा को तोड़ता है।