Was ist der richtige Weg, um ein InheritedWidget zu verwenden? Bisher habe ich verstanden, dass Sie damit die Möglichkeit haben, Daten über den Widget-Baum zu verbreiten. Wenn Sie als RootWidget angeben, ist es im Extremfall von allen Widgets im Baum auf allen Routen zugänglich, was in Ordnung ist, da ich mein ViewModel / Modell für meine Widgets irgendwie zugänglich machen muss, ohne auf Globals oder Singletons zurückgreifen zu müssen.
ABER InheritedWidget ist unveränderlich. Wie kann ich es aktualisieren? Und was noch wichtiger ist, wie werden meine Stateful Widgets ausgelöst, um ihre Teilbäume neu zu erstellen?
Leider ist die Dokumentation hier sehr unklar und nach vielen Diskussionen scheint niemand wirklich zu wissen, wie man sie richtig einsetzt.
Ich füge ein Zitat von Brian Egan hinzu:
Ja, ich sehe es als eine Möglichkeit, Daten im Baum zu verbreiten. Was ich aus den API-Dokumenten verwirrend finde:
"Wenn geerbte Widgets auf diese Weise referenziert werden, wird der Verbraucher neu erstellt, wenn das geerbte Widget selbst den Status ändert."
Als ich das zum ersten Mal las, dachte ich:
Ich könnte einige Daten in das InheritedWidget einfügen und später mutieren. Wenn diese Mutation auftritt, werden alle Widgets neu erstellt, die auf mein InheritedWidget verweisen. Was ich gefunden habe:
Um den Status eines InheritedWidget zu mutieren, müssen Sie ihn in ein StatefulWidget einschließen. Anschließend mutieren Sie den Status des StatefulWidget tatsächlich und geben diese Daten an das InheritedWidget weiter, das die Daten an alle untergeordneten Elemente weitergibt. In diesem Fall scheint jedoch der gesamte Baum unter dem StatefulWidget neu erstellt zu werden, nicht nur die Widgets, die auf das InheritedWidget verweisen. Ist das korrekt? Oder wird es irgendwie wissen, wie man die Widgets überspringt, die auf das InheritedWidget verweisen, wenn updateShouldNotify false zurückgibt?
quelle
MyInherited.of(context)
.updateShouldNotify
Test immer auf dieselbeMyInheritedState
Instanz bezieht , wird er nicht immer zurückgegebenfalse
? Sicherlich erstellt diebuild
MethodeMyInheritedState
neue_MyInherited
Instanzen, aber dasdata
Feld verweist immer aufthis
Nein? Ich habe Probleme ... Funktioniert, wenn ich nur harten Code habetrue
.TL; DR
Verwenden Sie keine umfangreichen Berechnungen innerhalb der updateShouldNotify- Methode und verwenden Sie beim Erstellen eines Widgets const anstelle von new
Zunächst sollten wir verstehen, was ein Widget-, Element- und Render-Objekt ist.
Jetzt können wir uns mit InheritedWidget und der BuildContext-Methode inheritFromWidgetOfExactType befassen .
Als Beispiel empfehle ich, dieses Beispiel aus Flatters Dokumentation über InheritedWidget zu betrachten:
InheritedWidget - nur ein Widget, das in unserem Fall eine wichtige Methode implementiert - updateShouldNotify . updateShouldNotify - eine Funktion, die einen Parameter oldWidget akzeptiert und einen booleschen Wert zurückgibt: true oder false.
Wie jedes Widget verfügt auch InheritedWidget über ein entsprechendes Element-Objekt. Es ist InheritedElement . InheritedElement ruft updateShouldNotify jedes Mal im Widget auf, wenn wir ein neues Widget erstellen (rufen Sie setState für einen Vorfahren auf). Wenn updateShouldNotify true zurückgibt , iteriert InheritedElement durch Abhängigkeiten (?) Und ruft die Methode didChangeDependencies auf.
Woher bekommt InheritedElement Abhängigkeiten ? Hier sollten wir uns die Methode inheritFromWidgetOfExactType ansehen .
inheritFromWidgetOfExactType - Diese in BuildContext definierte Methode und jedes Element implementiert die BuildContext-Schnittstelle (Element == BuildContext). Jedes Element hat also diese Methode.
Schauen wir uns den Code von inheritFromWidgetOfExactType an:
Hier versuchen wir, einen Vorfahren in _inheritedWidgets zu finden, der nach Typ zugeordnet ist. Wenn der Vorfahr gefunden wird, rufen wir inheritFromElement auf .
Der Code für inheritFromElement :
Jetzt wissen wir also, woher InheritedElement seine Abhängigkeiten bezieht.
Schauen wir uns nun die didChangeDependencies- Methode an. Jedes Element hat diese Methode:
Wie wir sehen können, markiert diese Methode nur ein Element als fehlerhaft und dieses Element sollte im nächsten Frame neu erstellt werden. Neu erstellen bedeutet , dass die Aufrufmethode auf dem entsprechenden Widget-Element basiert.
Aber was ist mit "Ganze Teilbäume werden neu erstellt, wenn ich InheritedWidget neu erstelle?". Hier sollten wir uns daran erinnern, dass Widgets unveränderlich sind und wenn Sie ein neues Widget erstellen, wird Flutter den Unterbaum neu erstellen. Wie können wir das beheben?
quelle
Aus den Dokumenten :
Wie das OP feststellte,
InheritedWidget
ändert sich eine Instanz nicht ... aber sie kann durch eine neue Instanz an derselben Stelle im Widget-Baum ersetzt werden. In diesem Fall müssen die registrierten Widgets möglicherweise neu erstellt werden. DieInheritedWidget.updateShouldNotify
Methode macht diese Bestimmung. (Siehe: Dokumente )Wie könnte eine Instanz ersetzt werden? Eine
InheritedWidget
Instanz kann in a enthalten seinStatefulWidget
, wodurch eine alte Instanz durch eine neue Instanz ersetzt werden kann.quelle
InheritedWidget verwaltet die Daten des App zentralisiert und an das Kind weitergeben, wie wir hier Warenkorb Zahl speichern können wie erläutert hier :
quelle