StatefulWidget vs StatelessWidget.
StatelessWidget - widget, który nie wymaga zmiany stanu.
Bezstanowy widget to widget, który opisuje część interfejsu użytkownika, tworząc konstelację innych widgetów, które opisują interfejs użytkownika bardziej konkretnie. Proces budowania jest kontynuowany rekurencyjnie, aż opis interfejsu użytkownika jest w pełni konkretny (np. Składa się w całości z RenderObjectWidgets, które opisują konkretne RenderObjects).
stateless
Widget jest przydatna, gdy część użytkownikowi interfejs ty opisujesz nie zależy od niczego innego niż informacji konfiguracyjnych w samym obiekcie i
BuildContext w którym widget jest zawyżone. W przypadku kompozycji, które mogą zmieniać się dynamicznie, np. Z powodu wewnętrznego stanu sterowanego zegarem lub w zależności od stanu systemu, rozważ użycie
StatefulWidget
.
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
StatefulWidget - widget, który ma zmienny stan.
- Widgety stanowe są przydatne, gdy opisywana część interfejsu użytkownika może zmieniać się dynamicznie.
Kiedy Flutter buduje obiekt StatefulWidget
, tworzy obiekt State. Ten obiekt jest miejscem, w którym przechowywany jest cały zmienny stan tego widżetu.
Pojęcie stanu definiują dwie rzeczy:
1) Dane używane przez widżet mogą ulec zmianie.
2) Dane nie mogą być odczytywane synchronicznie podczas budowania widgetu. (Cały stan musi zostać ustalony przed wywołaniem metody kompilacji).
Cykl życia StatefulWidget
Cykl życia składa się z następujących uproszczonych kroków:
- createState () - Gdy Flutter otrzymuje polecenie zbudowania StatefulWidget, natychmiast wywołuje
createState()
.
Tworzy zmienny stan dla tego widżetu w podanej lokalizacji w drzewie.
Podklasy powinny przesłonić tę metodę, aby zwrócić nowo utworzone wystąpienie skojarzonej z nimi podklasy State:
@override
_MyState createState() => _MyState();
- mount == true - Wszystkie widżety mają
this.mounted
właściwość bool . Okazuje się prawdą, gdy buildContext
zostanie przypisany. Błędem jest wywołanie, setState
gdy widget jest odmontowany. Czy ten obiekt State znajduje się obecnie w drzewie.
Po utworzeniu obiektu State i przed wywołaniem initState
struktura „montuje” obiekt State, kojarząc go z plikiem
BuildContext
. Obiekt State pozostaje zamontowany do momentu
wywołania frameworka dispose()
, po którym to czasie framework nigdy nie poprosi
obiektu State o ponowne zbudowanie.
Błędem jest wywoływanie setState, chyba że mount jest prawdziwe.
bool get mounted => _element != null;
- initState () - jest to pierwsza metoda wywoływana podczas tworzenia widgetu (oczywiście po konstruktorze klasy).
initState
jest wywoływana raz i tylko raz. To musi zadzwonićsuper.initState().
Zainicjuj dane, które zależą od określonego BuildContext dla utworzonego wystąpienia widżetu.
Zainicjuj właściwości, które opierają się na „rodzicu” tych widżetów w drzewie.
Zasubskrybuj strumienie ChangeNotifiers
lub dowolny inny obiekt, który może zmienić dane tego widżetu.
@override
initState() {
super.initState();
cartItemStream.listen((data) {
_updateWidget(data);
});
}
- didChangeDependencies () - wywoływana, gdy zmienia się zależność tego obiektu State.
Ta metoda jest również wywoływana bezpośrednio po initState
. Dzwonienie BuildContext.inheritFromWidgetOfExactType
z tej metody jest bezpieczne .
Podklasy rzadko zastępują tę metodę, ponieważ struktura zawsze wywołuje kompilację po zmianie zależności. Niektóre podklasy zastępują tę metodę, ponieważ muszą wykonać pewną kosztowną pracę (np. Pobieranie z sieci), gdy zmieniają się ich zależności, a ta praca byłaby zbyt kosztowna dla każdej kompilacji.
@protected
@mustCallSuper
void didChangeDependencies() { }
- build () - opisuje część interfejsu użytkownika reprezentowaną przez widżet.
Framework wywołuje tę metodę w wielu różnych sytuacjach:
- Po wezwaniu
initState
.
- Po wezwaniu
didUpdateWidget
.
- Po odebraniu telefonu
setState
.
- Po zmianie zależności tego obiektu State (np. InheritedWidget, do którego odwołują się poprzednie zmiany kompilacji).
- Po wywołaniu dezaktywuj, a następnie wstaw ponownie obiekt State do drzewa w innym miejscu.
Struktura zastępuje poddrzewo poniżej tego widżetu widżetem zwróconym przez tę metodę, aktualizując istniejące poddrzewo lub usuwając poddrzewo i wypełniając nowe poddrzewo, w zależności od tego, czy widżet zwrócony przez tę metodę może zaktualizować katalog główny istniejącego poddrzewa , jak ustalono dzwoniąc
Widget.canUpdate
.
Zazwyczaj implementacje zwracają nowo utworzoną konstelację widżetów, które są skonfigurowane przy użyciu informacji z konstruktora tego widgetu, danego elementu BuildContext oraz stanu wewnętrznego tego obiektu State.
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
- didUpdateWidget () - wywoływana po każdej zmianie konfiguracji widżetu.
Jeśli widget nadrzędny odbuduje się i zażąda, aby ta lokalizacja w drzewie zaktualizowała się w celu wyświetlenia nowego widgetu o tym samym typie środowiska wykonawczego i Widget.key, struktura zaktualizuje właściwość widgetu tego obiektu State, aby odwoływała się do nowego widgetu, a następnie wywoła to z poprzednim widżetem jako argumentem.
Zastąp tę metodę, aby reagować na zmiany widżetu (np. Aby rozpocząć niejawne animacje).
Framework zawsze wywołuje build po wywołaniu didUpdateWidget, co oznacza, że wszelkie wywołania setState w didUpdateWidget są zbędne.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
- setState () - za każdym razem, gdy zmieniasz stan wewnętrzny obiektu State, wprowadź zmianę w funkcji, do której przekazujesz
setState
:
Wywołanie setState powiadamia strukturę, że stan wewnętrzny tego obiektu zmienił się w sposób, który może wpłynąć na interfejs użytkownika w tym poddrzewie, co powoduje, że struktura planuje kompilację dla
tego obiektu State.
Jeśli po prostu zmienisz stan bezpośrednio bez wywoływania setState , struktura może nie zaplanować kompilacji, a interfejs użytkownika dla tego poddrzewa może nie zostać zaktualizowany w celu odzwierciedlenia nowego stanu.
setState(() { _myState = newValue });
- dezaktywować () - Deactivate jest wywoływane, gdy stan zostanie usunięty z drzewa, ale może zostać ponownie wstawiony przed zakończeniem bieżącej zmiany ramki. Ta metoda istnieje w zasadzie, ponieważ obiekty State można przenosić z jednego punktu w drzewie do drugiego.
- Struktura wywołuje tę metodę za każdym razem, gdy usuwa ten obiekt State z drzewa. W niektórych przypadkach framework ponownie wstawi obiekt State do innej części drzewa (np. Jeśli poddrzewo zawierające ten obiekt State jest przeszczepione z jednego miejsca w drzewie do drugiego). Jeśli tak się stanie, framework zapewni, że wywoła build, aby dać obiektowi State szansę na dostosowanie się do nowej lokalizacji w drzewie. Jeśli struktura rzeczywiście wstawi to poddrzewo, zrobi to przed końcem klatki animacji, w której poddrzewo zostało usunięte z drzewa. Z tego powodu obiekty State mogą odroczyć zwolnienie większości zasobów, dopóki struktura nie wywoła ich metody dispose.
Jest to rzadko używane.
@protected
@mustCallSuper
void deactivate() { }
- dispose () - wywoływana, gdy ten obiekt zostanie trwale usunięty z drzewa.
Struktura wywołuje tę metodę, gdy ten obiekt State nigdy nie zostanie ponownie utworzony. Po wywołaniach dispose()
struktury obiekt State jest uważany za odmontowany, a właściwość mount ma wartość false. W tym momencie wywołanie metody setState jest błędem. Ten etap cyklu życia jest ostateczny: nie ma możliwości ponownego zamontowania usuniętego obiektu State.
Podklasy powinny przesłonić tę metodę, aby zwolnić wszelkie zasoby zachowane przez ten obiekt (np. Zatrzymać wszelkie aktywne animacje).
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}
Więcej informacji można znaleźć tutaj , tutaj