Czy powinienem wywołać super.initState na końcu czy na początku?

10

Nie wiem, gdzie zadzwonić do super.initSate()trzepotania? W niektórych przykładach kodu jest on wywoływany na początku, a w innych na końcu. Czy jest jakaś różnica?

Próbowałem google go, ale nie znalazłem żadnego wyjaśnienia pozycji tego wywołania funkcji.

Który jest prawidłowy?

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

lub

void initState() {    
  //DO OTHER STUFF
  super.initState();    
}
K Vij
źródło

Odpowiedzi:

4

To ma znaczenie dla mixins (a także z tego powodu dla ciebie )

Jest to paradygmat w ramach Flutter do wywołania metody super-gdy przesłanianie metod cyklu życia w krótkim czasie State. Dlatego deactivatema nawet mustCallSuperadnotację .
Ponadto niektórzy mixinoczekują, że wywołasz super metody tych metod cyklu życia w określonym punkcie funkcji.

Oznacza to, że należy postępować zgodnie z dokumentacją i wezwanie super.dispose na końcu swojej disposemetody, ponieważ mixinów na Statew ramach spodziewać się, że jest to przypadek.
Na przykład: TickerProviderStateMixina assert na końcu:SingleTickerProviderStateMixin super.dispose

Wszystkie znaczniki muszą […] zostać usunięte przed wywołaniem super.dispose ().

Kolejny przykład: AutomaticKeepAliveMixinwykonuje logikę w initStatei dispose.

Wniosek

Start Your initStatezsuper.initState i zakończyć disposesięsuper.dispose , jeśli chcesz być na łatwej i bezpiecznej stronie dodanie mixins do swojej State.
Ponadto postępuj zgodnie z dokumentacją dotyczącą innych metod cyklu życia (dowolnej metody, którą zastąpisz State), ponieważ środowisko będzie oczekiwać, że wywołasz metody super, jak opisano w dokumentacji.

Dlatego należy wykonać następujące czynności:

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

Jednak tak naprawdę nie ma to znaczenia State, co wyjaśnię poniżej, a nawet dla mixin, ma znaczenie tylko dla stwierdzeń na podstawie tego, co mogłem znaleźć - więc nie wpłynie to na twoją aplikację produkcyjną.

To nie ma znaczenia State

Myślę, że dwie poprzednie odpowiedzi Pabla Barrery i CopsOnRoadmylące, ponieważ prawda jest taka, że ​​to naprawdę nie ma znaczenia i nie trzeba daleko szukać.

Jedyne czynności, które super.initStatei super.disposebiorą w Stateklasie sama są twierdzenia , a od assert-statements są oceniane tylko w trybie debugowania , to nie ma znaczenia w ogóle raz kompilacja aplikacji, czyli w trybie produkcyjnym.


Poniżej poprowadzę cię przez to, co super.initStatei co super.disposerobisz State, czyli cały kod, który zostanie wykonany, gdy nie będziesz mieć dodatkowych miksów.

initState

Przyjrzyjmy się dokładnie, jaki kod jest super.initStatenajpierw wykonywany ( źródło ):

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

Jak widać, istnieje tylko stwierdzenie dotyczące cyklu życia, a jego celem jest zapewnienie prawidłowego działania widgetu. Tak długo, jak dzwonisz super.initState gdzieś we własnym zakresie initState, zobaczysz komunikat, AssertionErrorczy widżet nie działa zgodnie z przeznaczeniem. Nie ma znaczenia, czy podjąłeś jakieś wcześniejsze działania, ponieważ assertma to na celu wyłącznie zgłoszenie, że coś w twoim kodzie i tak jest złe i zobaczysz to, nawet jeśli zadzwonisz super.initStatena samym końcu metody.

dispose

disposeSposób analogiczny ( źródło )

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() {
    _debugLifecycleState = _StateLifecycle.defunct;
    return true;
  }());
}

Jak widać, zawiera także tylko twierdzenia, które obsługują sprawdzanie cyklu życia debugowania . Drugi asserttutaj jest fajną sztuczką, ponieważ zapewnia, że _debugLifecycleStatezmienia się tylko w trybie debugowania (ponieważ assert-statements są wykonywane tylko w trybie debugowania).
Oznacza to, że dopóki zadzwonisz super.dispose gdzieś własną metodą, nie stracisz żadnej wartości bez dodania dodatkowej funkcjonalności przez mixiny.

creativecreatorormaybenot
źródło
1
Oficjalne dokumenty
Fluttera
Dziękuję za wyjaśnienie, czy mógłbyś również wyjaśnić, że istnieje tylko jedna linia w initState()metodzie assert(...), więc jaka jest korzyść z nawet wywołania super.initState()aplikacji produkcyjnej?
CopsOnRoad
1
Wielkie dzięki. Teraz to ma sens! Sądzę więc, że jestem po bezpieczniejszej stronie i ze względu na dobrą praktykę programowania dobrze jest zachować ją na początku kodu.
K Vij
@creativecreatorormaybenot Oznacza to, że zespół Flutter oszalał, wprowadzając mustCallSupertę metodę od ponad 2 lat, odkąd Flutter powstał. Jaka jest korzyść z umieszczenia go tutaj?
CopsOnRoad
@creativecreatorormaybenot Nawet jeśli zespół stworzył go mixin, nadal tam będzie jeden rachunek w tym initStateco jest assert(...), więc co to znaczenie nawet dzwoniąc super.initState()do aplikacji produkcji?
CopsOnRoad
3

super.initState()powinien zawsze być pierwszym wierszem w Twojej initStatemetodzie.

Z dokumentów:

initState (): Jeśli to przesłonisz, upewnij się, że twoja metoda zaczyna się od wywołania super.initState ().

CopsOnRoad
źródło
2

Jak widać w klasach z frameworka, powinieneś zrobić wszystko po zainicjowaniu widgetu, czyli po super.initState().

W przypadku wyrzucenia byłoby logicznie w inny sposób, najpierw zrobić wszystko, a następnie zadzwonić super.dispose().

@override
void initState() {
  super.initState();
  // DO STUFF
}

@override
void dispose() {
  // DO STUFF
  super.dispose();
}
Pablo Barrera
źródło
Dzięki. Zauważyłem to jednak w niektórych przykładach kodu. nazywa się na końcu metody initState ...
K Vij
Tak powiedziałem
Pablo Barrera
0

initState wywoływane domyślnie za każdym razem, gdy do drzewa widżetów dodawany jest nowy widget stanowy. Teraz super.initState wykonuje domyślną implementację klasy podstawowej widgetu. Jeśli wywołasz coś przed super.initState, która zależy od klasy podstawowej, może to powodować problem. Dlatego zaleca się, aby wywoływać initState w następujący sposób:

@override
void initState() {
  super.initState();
  // DO STUFF
}
Anirudh Sharma
źródło
Rozumowanie jest nieco błędne, ponieważ disposejest odwrotnie. Struktura oczekuje, że zadzwonisz super.dispose na końcu , ale zalecenie jest poprawne.
creativecreatorormaybenot
Ponieważ jeśli wywołasz super.dispose przed pozbyciem się innych rzeczy, komponenty zależne od twojej klasy podstawowej mogą się kolidować.
Anirudh Sharma