Devo chiamare super.initState alla fine o all'inizio?


10

Sono confuso su dove chiamare il super.initSate()flutter? In alcuni esempi di codice viene chiamato all'inizio e in altri alla fine. C'è una differenza?

Ho provato a cercarlo su Google, ma non ho trovato alcuna spiegazione sulla posizione di questa chiamata di funzione.

Quale è corretto?

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

o

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

Risposte:


4

E non importa per mixins (e per questo per voi pure)

È un paradigma nel framework Flutter chiamare il metodo super quando si sovrascrivono i metodi del ciclo di vita in a State. Questo è il motivo per cui deactivateha anche mustCallSuperun'annotazione .
Inoltre , alcuni si mixinaspettano che tu chiami i super metodi di quei metodi del ciclo di vita in un determinato punto della funzione.

Questo significa che si dovrebbe seguire la documentazione e la chiamata super.dispose alla fine del disposemetodo, perché mixins sul Statenell'ambito aspettano che questo è il caso.
Ad esempio: TickerProviderStateMixine affermare alla fine:SingleTickerProviderStateMixin super.dispose

Tutti i ticker devono [..] essere eliminati prima di chiamare super.dispose ().

Un altro esempio: AutomaticKeepAliveMixinesegue la logica in initStatee dispose.

Conclusione

Inizia initStateconsuper.initState e termina disposeconsuper.dispose se vuoi essere sul lato facile e sicuro aggiungendo mixins al tuo State.
Inoltre, seguire la documentazione per altri metodi del ciclo di vita (qualsiasi metodo in cui si sovrascrive State) perché il framework prevede che si chiamino i super metodi come descritto nella documentazione.

Quindi, ciò che dovresti fare è il seguente:

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

Tuttavia, non importa davveroState , cosa che spiegherò nel seguito e anche per i mixin, importa solo per le affermazioni a giudicare da ciò che ho potuto trovare, quindi non influirebbe sulla tua app di produzione.

Non importa per State

Penso che le due precedenti risposte di Pablo Barrera e CopsOnRoad siano fuorvianti perché la verità è che non importa davvero e non è necessario guardare lontano.

Le uniche azioni che super.initStatee super.disposeprendono nella Stateclasse stessa sono affermazioni e dal momento che assert-statements vengono valutati solo in modalità debug , non importa a tutti una volta creare l'app, cioè in modalità di produzione.


Di seguito, ti guiderò attraverso cosa super.initStatee cosa super.disposefare State, che è tutto il codice che verrà eseguito quando non hai altri mixin.

initState

Vediamo esattamente quale codice viene eseguito per super.initStateprimo ( sorgente ):

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

Come puoi vedere, esiste solo un'asserzione del ciclo di vita e lo scopo è garantire che il tuo widget funzioni correttamente. Quindi, finché chiami super.initState da qualche parte nel tuo initState, vedrai un AssertionErrorse il tuo widget non funziona come previsto. Non importa se hai intrapreso qualche azione precedente perché assertintende solo segnalare che qualcosa nel tuo codice è sbagliato comunque e lo vedrai anche se chiami super.initStatealla fine del tuo metodo.

dispose

Il disposemetodo è analogo ( fonte ):

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

Come puoi vedere, contiene anche solo asserzioni che gestiscono il controllo del ciclo di vita del debug . Il secondo assertqui è un bel trucco perché assicura che _debugLifecycleStatesia cambiato solo in modalità debug (poiché gli assertstati vengono eseguiti solo in modalità debug).
Ciò significa che finché chiami super.dispose da qualche parte nel tuo metodo, non perderai alcun valore senza che i mixin aggiungano funzionalità aggiuntive.


1
I documenti ufficiali di Flutter non sono molto buoni :( grazie per la risposta :)
CopsOnRoad

Grazie per la tua spiegazione, ti dispiacerebbe anche spiegare, c'è solo una riga nel initState()metodo che è assert(...), quindi qual è il vantaggio di persino chiamare super.initState()nell'app di produzione?
CopsOnRoad,

1
Grazie mille. Adesso ha senso! Quindi immagino di essere sul lato più sicuro e per motivi di buone pratiche di programmazione è bene tenerlo all'inizio del codice.
K Vij,

@creativecreatorormaybenot Ciò significa che il team Flutter è fuori di testa mettendo mustCallSuperin pratica questo metodo per più di 2 anni da quando Flutter è nato. Qual è il vantaggio di metterlo lì signore?
CopsOnRoad,

@creativecreatorormaybenot Anche se il team lo ha creato per mixin, ci sarà comunque una singola affermazione in questo initStateche è assert(...), quindi qual è il significato persino di richiedere super.initState()un'app di produzione?
CopsOnRoad,

3

super.initState()dovrebbe sempre essere la prima riga del tuo initStatemetodo.

Da documenti:

initState (): se lo sostituisci, assicurati che il tuo metodo inizi con una chiamata a super.initState ().


2

Come puoi vedere nelle classi dal framework, dovresti fare tutto dopo l'inizializzazione del widget, ovvero dopo super.initState().

Il caso di disporre sarebbe logicamente nell'altro modo, prima fare tutto e poi chiamare super.dispose().

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

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

Grazie. Ma ho notato che in alcuni esempi di codice. viene chiamato alla fine del metodo initState ...
K Vij,

Questo è quello che ho detto
Pablo Barrera il

0

initState viene richiamato per impostazione predefinita ogni volta che un nuovo widget stateful viene aggiunto in una struttura di widget. Ora super.initState esegue l'implementazione predefinita della classe base del tuo widget. Se chiami qualcosa prima di super.initState che dipende dalla classe base, ciò potrebbe causare problemi. Ecco perché si consiglia di chiamare initState in questo modo:

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

Il ragionamento è un po 'imperfetto perché disposeè l'opposto. Il quadro si aspetta di chiamare super.dispose alla fine , ma la raccomandazione è corretta.
creativecreatorormaybenot

Perché se chiami super.dispose prima di smaltire le altre cose, i componenti che dipendono dalla tua classe base potrebbero scontrarsi.
Anirudh Sharma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.