Jaki jest prawidłowy sposób korzystania z InheritedWidget? Jak dotąd zrozumiałem, że daje to szansę na propagowanie danych w drzewie widżetów. W skrajnym przypadku, jeśli umieścisz jako RootWidget, będzie on dostępny ze wszystkich widżetów w drzewie na wszystkich trasach, co jest w porządku, ponieważ w jakiś sposób muszę udostępnić mój ViewModel / Model dla moich widżetów bez konieczności uciekania się do globali lub singletonów.
ALE InheritedWidget jest niezmienny, więc jak mogę go zaktualizować? A co ważniejsze, w jaki sposób są uruchamiane moje Stateful Widgets, aby odbudować ich poddrzewa?
Niestety dokumentacja jest tutaj bardzo niejasna i po wielu dyskusjach wydaje się, że nikt tak naprawdę nie wie, jaki jest prawidłowy sposób jej użycia.
Dodaję cytat z Briana Egana:
Tak, uważam to za sposób na propagowanie danych w dół drzewa. To, co uważam za mylące, z dokumentacji API:
„Dziedziczone widżety przywoływane w ten sposób spowodują, że konsument będzie przebudowywał, gdy odziedziczony widżet sam zmieni stan”.
Kiedy po raz pierwszy to przeczytałem, pomyślałem:
Mógłbym umieścić niektóre dane w InheritedWidget i zmodyfikować je później. Kiedy ta mutacja nastąpi, odbuduje wszystkie widżety, które odwołują się do mojego InheritedWidget Co znalazłem:
Aby zmutować stan InheritedWidget, musisz opakować go w StatefulWidget. Następnie faktycznie dokonujesz mutacji stanu StatefulWidget i przekazujesz te dane do InheritedWidget, który przekazuje dane wszystkim swoim elementom podrzędnym. Jednak w tym przypadku wydaje się, że odbudowuje całe drzewo pod StatefulWidget, a nie tylko widżety, które odwołują się do InheritedWidget. Czy to jest poprawne? A może w jakiś sposób będzie wiedziało, jak pominąć widżety, które odwołują się do InheritedWidget, jeśli updateShouldNotify zwróci false?
źródło
MyInherited.of(context)
.updateShouldNotify
test zawsze odnosi się do tej samejMyInheritedState
instancji, czy nie zawsze zwrócifalse
? Z pewnościąbuild
metodaMyInheritedState
polega na tworzeniu nowych_MyInherited
instancji, aledata
pole zawsze odwołuje się dothis
nie? Mam problemy ... Działa, jeśli tylko napiszę kodtrue
.TL; DR
Nie używaj ciężkich obliczeń w metodzie updateShouldNotify i używaj const zamiast new podczas tworzenia widgetu
Przede wszystkim powinniśmy zrozumieć, czym są obiekty Widget, Element i Render.
Teraz jesteśmy gotowi do zanurzenia się w InheritedWidget i metodzie BuildContext inheritFromWidgetOfExactType .
Jako przykład, który polecam, rozważmy następujący przykład z dokumentacji Fluttera na temat InheritedWidget:
InheritedWidget - po prostu widżet, który implementuje w naszym przypadku jedną ważną metodę - updateShouldNotify . updateShouldNotify - funkcja, która przyjmuje jeden parametr oldWidget i zwraca wartość logiczną: true lub false.
Jak każdy widżet, InheritedWidget ma odpowiedni obiekt Element. To jest InheritedElement . InheritedElement wywołuje updateShouldNotify na widgecie za każdym razem, gdy tworzymy nowy widget (wywołanie setState na przodku). Gdy updateShouldNotify zwraca wartość true, InheritedElement wykonuje iterację przez zależności (?) I wywołuje metodę didChangeDependencies .
Gdzie InheritedElement pobiera zależności ? Tutaj powinniśmy spojrzeć na metodę inheritFromWidgetOfExactType .
inheritFromWidgetOfExactType - ta metoda zdefiniowana w BuildContext i każdy element implementuje interfejs BuildContext (Element == BuildContext). Więc każdy element ma tę metodę.
Spójrzmy na kod inheritFromWidgetOfExactType:
Tutaj próbujemy znaleźć przodka w _inheritedWidgets zmapowanych według typu. Jeśli przodek zostanie znaleziony, wywołujemy inheritFromElement .
Kod inheritFromElement :
Więc teraz wiemy, skąd InheritedElement pobiera swoje zależności.
Spójrzmy teraz na metodę didChangeDependencies . Każdy element ma tę metodę:
Jak widzimy ta metoda po prostu zaznacza element jako brudny i ten element należy odbudować w następnej klatce. Odbudować metody środki połączenia build na coresponding widget elementu.
Ale co z „Przebudowaniem całego poddrzewa, gdy odbuduję InheritedWidget?”. Tutaj powinniśmy pamiętać, że widżety są niezmienne i jeśli utworzysz nowy widget, Flutter odbuduje poddrzewo. Jak możemy to naprawić?
źródło
Z dokumentów :
Jak zauważył OP,
InheritedWidget
instancja się nie zmienia ... ale można ją zastąpić nową instancją w tym samym miejscu w drzewie widżetów. W takim przypadku możliwe jest, że zarejestrowane widgety będą wymagały odbudowy.InheritedWidget.updateShouldNotify
Metoda czyni tę determinację. (Zobacz: dokumentacja )Jak więc można wymienić instancję?
InheritedWidget
Przykład może być zawarty przezStatefulWidget
, które mogą zastąpić stary wystąpienie nową np.źródło
InheritedWidget zarządza scentralizowanymi danymi aplikacji i przekazuje je dziecku, tak jak możemy przechowywać tutaj liczbę koszyków, jak wyjaśniono tutaj :
źródło