StatefulWidget vs StatelessWidget.
StatelessWidget - Ein Widget, für das kein veränderbarer Status erforderlich ist.
Ein zustandsloses Widget ist ein Widget, das einen Teil der Benutzeroberfläche beschreibt, indem eine Konstellation anderer Widgets erstellt wird, die die Benutzeroberfläche konkreter beschreiben. Der Erstellungsprozess wird rekursiv fortgesetzt, bis die Beschreibung der Benutzeroberfläche vollständig konkret ist (z. B. vollständig aus RenderObjectWidgets besteht, die konkrete RenderObjects beschreiben).
Das stateless
Widget ist nützlich, wenn der von Ihnen beschriebene Teil der Benutzeroberfläche nur von den Konfigurationsinformationen im Objekt selbst und dem
BuildContext abhängt, in dem das Widget aufgeblasen ist. Bei Kompositionen, die sich dynamisch ändern können, z. B. aufgrund eines internen taktgesteuerten Zustands oder abhängig von einem bestimmten Systemzustand, sollten Sie die Verwendung in Betracht ziehen
StatefulWidget
.
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
StatefulWidget - Ein Widget mit veränderlichem Status.
- Stateful-Widgets sind nützlich, wenn sich der von Ihnen beschriebene Teil der Benutzeroberfläche dynamisch ändern kann.
Wenn Flutter a baut StatefulWidget
, wird ein erstellt. In diesem Objekt befindet sich der gesamte veränderbare Status für dieses Widget.
Der Begriff des Staates wird durch zwei Dinge definiert:
1) Die vom Widget verwendeten Daten können sich ändern.
2) Die Daten können beim Erstellen des Widgets nicht synchron gelesen werden. (Alle Zustände müssen zum Zeitpunkt des Aufrufs der Erstellungsmethode festgelegt sein.)
StatefulWidget-Lebenszyklus
Der Lebenszyklus besteht aus folgenden vereinfachten Schritten:
- createState () - Wenn Flutter angewiesen wird, ein StatefulWidget zu erstellen, wird es sofort aufgerufen
createState()
.
Erstellt den veränderlichen Status für dieses Widget an einer bestimmten Stelle im Baum.
Unterklassen sollten diese Methode überschreiben, um eine neu erstellte Instanz ihrer zugeordneten Statusunterklasse zurückzugeben:
@override
_MyState createState() => _MyState();
- mount == true - Alle Widgets haben eine bool-
this.mounted
Eigenschaft. Es wird wahr, wenn das buildContext
zugewiesen ist. Es ist ein Fehler beim Aufrufen, setState
wenn ein Widget nicht gemountet ist. Gibt an, ob sich dieses Statusobjekt derzeit in einem Baum befindet.
Nach dem Erstellen eines Statusobjekts und vor dem Aufrufen initState
"mountet" das Framework das Statusobjekt, indem es mit a verknüpft wird
BuildContext
. Das State-Objekt bleibt bis zum Aufruf des Frameworks gemountet. Danach
fordert dispose()
das Framework das
State-Objekt nie mehr auf, es erneut zu erstellen.
Es ist ein Fehler, setState aufzurufen, es sei denn, mount ist true.
bool get mounted => _element != null;
- initState () - Dies ist die erste Methode, die beim Erstellen des Widgets aufgerufen wird (natürlich nach dem Klassenkonstruktor).
initState
wird einmal und nur einmal aufgerufen. Es muss anrufensuper.initState().
Initialisieren Sie Daten, die auf dem spezifischen BuildContext für die erstellte Instanz des Widgets basieren.
Initialisieren Sie Eigenschaften, die auf diesen übergeordneten Widgets im Baum basieren.
Abonnieren Sie Streams ChangeNotifiers
oder andere Objekte, die die Daten in diesem Widget ändern könnten.
@override
initState() {
super.initState();
// Add listeners to this class
cartItemStream.listen((data) {
_updateWidget(data);
});
}
- didChangeDependencies () - Wird aufgerufen, wenn sich eine Abhängigkeit dieses Statusobjekts ändert.
Diese Methode wird auch unmittelbar danach aufgerufen initState
. Es ist sicher, BuildContext.inheritFromWidgetOfExactType
von dieser Methode aufzurufen .
Unterklassen überschreiben diese Methode selten, da das Framework Build immer nach Abhängigkeitsänderungen aufruft. Einige Unterklassen überschreiben diese Methode, da sie teure Arbeit (z. B. Netzwerkabrufe) ausführen müssen, wenn sich ihre Abhängigkeiten ändern, und diese Arbeit für jeden Build zu teuer wäre.
@protected
@mustCallSuper
void didChangeDependencies() { }
- build () - Beschreibt den Teil der Benutzeroberfläche, der vom Widget dargestellt wird.
Das Framework ruft diese Methode in verschiedenen Situationen auf:
- Nach dem Anruf
initState
.
- Nach dem Anruf
didUpdateWidget
.
- Nach einem Anruf bei
setState
.
- Nach einer Abhängigkeit dieses Status ändert sich das Objekt (z. B. ein InheritedWidget, auf das durch die vorherigen Build-Änderungen verwiesen wurde).
- Nach dem Aufruf deaktivieren und dann das Statusobjekt an einer anderen Stelle wieder in den Baum einfügen.
Das Framework ersetzt den Teilbaum unter diesem Widget durch das von dieser Methode zurückgegebene Widget, indem entweder der vorhandene Teilbaum aktualisiert oder der Teilbaum entfernt und ein neuer Teilbaum aufgeblasen wird, je nachdem, ob das von dieser Methode zurückgegebene Widget den Stamm des vorhandenen Teilbaums aktualisieren kann , wie durch Anruf bestimmt
Widget.canUpdate
.
In der Regel geben Implementierungen eine neu erstellte Konstellation von Widgets zurück, die mit Informationen aus dem Konstruktor dieses Widgets, dem angegebenen BuildContext und dem internen Status dieses Statusobjekts konfiguriert sind .
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
- didUpdateWidget () - Wird aufgerufen, wenn sich die Widget-Konfiguration ändert.
Wenn das übergeordnete Widget neu erstellt wird und anfordert, dass dieser Speicherort in der Baumstruktur aktualisiert wird, um ein neues Widget mit demselben Laufzeittyp und demselben Widget.key anzuzeigen, aktualisiert das Framework die Widget-Eigenschaft dieses Statusobjekts, um auf das neue Widget zu verweisen, und ruft dies dann auf Methode mit dem vorherigen Widget als Argument.
Überschreiben Sie diese Methode, um zu reagieren, wenn sich das Widget ändert (z. B. um implizite Animationen zu starten).
Das Framework ruft Build nach dem Aufruf von didUpdateWidget immer auf. Dies bedeutet, dass alle Aufrufe von setState in didUpdateWidget redundant sind.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
- setState () - Wenn Sie den internen Status eines Statusobjekts ändern, nehmen Sie die Änderung an einer Funktion vor, an die Sie übergeben
setState
:
Durch Aufrufen von setState wird das Framework benachrichtigt, dass sich der interne Status dieses Objekts so geändert hat, dass sich dies auf die Benutzeroberfläche in diesem Teilbaum auswirken kann. Dadurch plant das Framework einen Build für
dieses Statusobjekt.
Wenn Sie den Status nur direkt ändern , ohne setState aufzurufen, plant das Framework möglicherweise keinen Build und die Benutzeroberfläche für diesen Teilbaum wird möglicherweise nicht aktualisiert, um den neuen Status widerzuspiegeln.
setState(() { _myState = newValue });
- disable () - Deaktivieren wird aufgerufen, wenn State aus dem Baum entfernt wird. Es kann jedoch erneut eingefügt werden, bevor der aktuelle Frame-Wechsel abgeschlossen ist. Diese Methode existiert im Wesentlichen, weil Statusobjekte von einem Punkt in einem Baum zu einem anderen verschoben werden können.
- Das Framework ruft diese Methode immer dann auf, wenn es dieses Statusobjekt aus dem Baum entfernt. In einigen Fällen fügt das Framework das Statusobjekt erneut in einen anderen Teil des Baums ein (z. B. wenn der Teilbaum, der dieses Statusobjekt enthält, von einer Stelle im Baum an eine andere übertragen wird). In diesem Fall stellt das Framework sicher, dass es build aufruft, um dem State-Objekt die Möglichkeit zu geben, sich an seine neue Position im Baum anzupassen. Wenn das Framework diesen Teilbaum erneut einfügt, erfolgt dies vor dem Ende des Animationsrahmens, in dem der Teilbaum aus dem Baum entfernt wurde. Aus diesem Grund können Statusobjekte die Freigabe der meisten Ressourcen verschieben, bis das Framework ihre Entsorgungsmethode aufruft.
Dies wird selten verwendet.
@protected
@mustCallSuper
void deactivate() { }
- dispose () - Wird aufgerufen, wenn dieses Objekt dauerhaft aus dem Baum entfernt wird.
Das Framework ruft diese Methode auf, wenn dieses Statusobjekt nie wieder erstellt wird. Nach den Framework-Aufrufen dispose()
wird das Statusobjekt als nicht bereitgestellt betrachtet und die bereitgestellte Eigenschaft ist falsch. Es ist ein Fehler, an dieser Stelle setState aufzurufen. Diese Phase des Lebenszyklus ist endständig: Es gibt keine Möglichkeit, ein entsorgtes Statusobjekt erneut bereitzustellen.
Unterklassen sollten diese Methode überschreiben, um alle von diesem Objekt beibehaltenen Ressourcen freizugeben (z. B. aktive Animationen zu stoppen).
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}
Weitere Informationen finden Sie hier hier , hier