Aus verschiedenen Gründen wird die build
Methode meiner Widgets manchmal erneut aufgerufen.
Ich weiß, dass es passiert, weil ein Elternteil aktualisiert hat. Dies führt jedoch zu unerwünschten Effekten. Eine typische Situation, in der Probleme auftreten, ist die folgende FutureBuilder
:
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: httpCall(),
builder: (context, snapshot) {
// create some layout here
},
);
}
Wenn in diesem Beispiel die Erstellungsmethode erneut aufgerufen wird, wird eine weitere http-Anforderung ausgelöst. Welches ist unerwünscht.
Wie geht man in Anbetracht dessen mit unerwünschten Builds um? Gibt es eine Möglichkeit, einen Build-Aufruf zu verhindern?
flutter
flutter-widget
Rémi Rousselet
quelle
quelle
Antworten:
Die Erstellungsmethode ist so konzipiert, dass sie rein / ohne Nebenwirkungen sein sollte . Dies liegt daran, dass viele externe Faktoren einen neuen Widget-Build auslösen können, z.
Class.of(context)
Muster-) ÄnderungDies bedeutet, dass die
build
Methode keinen http-Aufruf auslösen oder einen Status ändern sollte .Wie hängt das mit der Frage zusammen?
Das Problem, mit dem Sie konfrontiert sind, besteht darin, dass Ihre Erstellungsmethode Nebenwirkungen hat / nicht rein ist, was einen fremden Erstellungsaufruf problematisch macht.
Anstatt einen Build-Aufruf zu verhindern, sollten Sie Ihre Build-Methode rein machen, damit sie jederzeit ohne Auswirkungen aufgerufen werden kann.
Im Fall von Ihrem Beispiel, würden Sie das Widget in eine Transformation
StatefulWidget
dann die , dass die HTTP - Aufruf extrahiertinitState
IhreState
:Es ist auch möglich, ein Widget neu zu erstellen, ohne dass seine Kinder ebenfalls zum Erstellen gezwungen werden.
Wenn die Instanz eines Widgets gleich bleibt; Flattern baut Kinder absichtlich nicht wieder auf. Dies bedeutet, dass Sie Teile Ihres Widget-Baums zwischenspeichern können, um unnötige Neuerstellungen zu vermeiden.
Der einfachste Weg ist die Verwendung von Dartkonstruktoren
const
:Dank dieses
const
SchlüsselwortsDecoratedBox
bleibt die Instanz von gleich, auch wenn der Build hunderte Male aufgerufen wurde.Sie können jedoch das gleiche Ergebnis manuell erzielen:
In diesem Beispiel wird StreamBuilder, wenn er über neue Werte benachrichtigt
subtree
wird, auch dann nicht neu erstellt, wenn StreamBuilder / Column dies tut. Es passiert, weil sich dank der Schließung die Instanz vonMyWidget
nicht geändert hat.Dieses Muster wird häufig in Animationen verwendet. Typische Verwendungen sind
AnimatedBuilder
und alle Übergänge wieAlignTransition
.Sie können auch
subtree
in einem Feld Ihrer Klasse speichern , obwohl dies weniger empfohlen wird, da dadurch die Hot-Reload-Funktion unterbrochen wird.quelle
subtree
in einem Klassenfeld das Hot-Reload unterbricht?StreamBuilder
tun habe, ist, dass sich der Bildschirm ändert, wenn die Tastatur angezeigt wird, sodass Routen neu erstellt werden müssen. AlsoStreamBuilder
wird neu aufgebaut und ein neuesStreamBuilder
erstellt und es abonniert dasstream
. Wenn a einStreamBuilder
abonniertstream
,snapshot.connectionState
wirdConnectionState.waiting
, wodurch mein Code a zurückgibtCircularProgressIndicator
, undsnapshot.connectionState
ändert sich dann , wenn Daten vorhanden sind, und mein Code gibt ein anderes Widget zurück, wodurch der Bildschirm mit verschiedenen Dingen flackert.StatefulWidget
, abonniere dasstream
oninitState()
und setze dascurrentWidget
mit,setState()
wennstream
neue Daten gesendet werden, und übergebe escurrentWidget
an diebuild()
Methode. Gibt es eine bessere Lösung?FutureBuilder
.Auf diese Weise können Sie unerwünschte Build-Aufrufe verhindern
1) Erstellen Sie eine untergeordnete Statefull-Klasse für einen einzelnen kleinen Teil der Benutzeroberfläche
2) Verwenden Sie Provider - Bibliothek, indem es so können Sie unerwünschte Build - Methode aufrufen stoppen
In diese Situation unten build Methodenaufruf
quelle
Flattern hat auch
ValueListenableBuilder<T> class
. Sie können nur einige der für Ihren Zweck erforderlichen Widgets neu erstellen und die teuren Widgets überspringen.Sie können die Dokumente hier sehen. ValueListenableBuilder flattert Dokumente
oder nur den folgenden Beispielcode:
quelle