¿Debo llamar a super.initState al final o al principio?

10

Estoy confundido en cuanto a dónde llamar al super.initSate()flutter? En algunos ejemplos de código se llama al principio y en otros al final. ¿Hay una diferencia?

He intentado googlear esto pero no he encontrado ninguna explicación sobre la posición de esta llamada de función.

¿Cuál es el correcto?

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

o

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

Respuestas:

4

Importa para mixins (y por eso también para ti )

Es un paradigma en el marco de Flutter llamar al súper método al anular los métodos de ciclo de vida en a State. Es por eso que incluso deactivatetiene una mustCallSuperanotación .
Además , algunos mixinesperan que llame a los súper métodos de esos métodos de ciclo de vida en un punto particular de la función.

Esto significa que debe seguir la documentación y llamar super.dispose al final de su disposemétodo porque mixins Stateen el marco espera que este sea el caso.
Por ejemplo: TickerProviderStateMixiny afirmar al final:SingleTickerProviderStateMixin super.dispose

Todos los Tickers deben [..] eliminarse antes de llamar a super.dispose ().

Otro ejemplo: AutomaticKeepAliveMixinejecuta lógica en initStatey dispose.

Conclusión

Comience initStateconsuper.initState y termine disposecon consuper.dispose si desea estar en el lado fácil y seguro agregando mixins a su State.
Además, siga la documentación para otros métodos de ciclo de vida (cualquier método que sobrescriba State) porque el marco esperará que llame a los súper métodos como se describe en la documentación.

Por lo tanto, lo siguiente es lo que debe hacer:

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

Sin embargo, en realidad no importa State, lo que explicaré a continuación e incluso para los mixins, solo importa para las afirmaciones a juzgar por lo que pude encontrar, por lo que no afectaría su aplicación de producción.

No importa para State

Creo que las dos respuestas anteriores de Pablo Barrera y CopsOnRoad son engañosas porque la verdad del asunto es que realmente no importa y no es necesario mirar muy lejos.

Las únicas acciones que super.initStatey super.disposetoman en la Statepropia clase son las aseveraciones y desde assert-statements se evalúan sólo en modo de depuración , no importa en absoluto una vez que construir su aplicación, es decir, en el modo de producción.


A continuación, lo guiaré a través de qué super.initStatey qué super.disposehacer State, que es todo el código que se ejecutará cuando no tenga mixins adicionales.

initState

Veamos exactamente qué código se ejecuta super.initStateprimero ( fuente ):

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

Como puede ver, solo hay una afirmación del ciclo de vida y su propósito es garantizar que su widget funcione correctamente. Por lo tanto, siempre que llame a super.initState algún lugar por su cuenta initState, verá AssertionErrorsi su widget no funciona según lo previsto. No importa si tomó alguna acción previa porque assertsolo tiene el propósito de informar que algo en su código está mal de todos modos y lo verá incluso si llama super.initStateal final de su método.

dispose

El disposemétodo es análogo ( fuente ):

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

Como puede ver, también solo contiene aserciones que manejan la verificación del ciclo de vida de depuración . El segundo assertaquí es un buen truco porque garantiza que _debugLifecycleStatesolo se cambie en modo de depuración (ya que las assertdeclaraciones solo se ejecutan en modo de depuración).
Esto significa que siempre que llame a super.dispose algún lugar con su propio método, no perderá ningún valor sin que los mixins agreguen funcionalidad adicional.

creativecreatorormaybenot
fuente
1
Los documentos oficiales de Flutter no son muy buenos :( gracias por tu respuesta :)
CopsOnRoad
Gracias por su explicación, ¿también le importaría explicarlo? Solo hay una línea en el initState()método assert(...), ¿cuál es el beneficio de incluso llamar super.initState()a la aplicación de producción?
CopsOnRoad
1
Muchas gracias. ¡Ahora tiene sentido! Así que supongo que para estar más seguro y en aras de una buena práctica de programación, es bueno mantenerlo al comienzo del código.
K Vij
@creativecreatorormaybenot Eso significa que el equipo de Flutter está loco al poner mustCallSuperese método durante más de 2 años desde que Flutter nació. ¿Cuál es el beneficio de ponerlo allí, señor?
CopsOnRoad
@creativecreatorormaybenot Incluso si el equipo ha creado para mixin, todavía no va a ser una sola instrucción en este initStateque es assert(...), ¿cuál es el significado de incluso llamando super.initState()para una aplicación de producción?
CopsOnRoad
3

super.initState()siempre debe ser la primera línea en su initStatemétodo.

De documentos:

initState (): si anula esto, asegúrese de que su método comience con una llamada a super.initState ().

PolicíasEn Carretera
fuente
2

Como puede ver en las clases del marco, debe hacer todo después de inicializar el widget, es decir, después super.initState().

En caso de disponer sería lógicamente de otra manera, primero haga todo y luego llame super.dispose().

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

@override
void dispose() {
  // DO STUFF
  super.dispose();
}
Pablo Barrera
fuente
Gracias. Pero he notado eso en algunos ejemplos de código. se llama al final del método initState ...
K Vij
Eso es lo que dije
Pablo Barrera el
0

initState se llama por defecto cada vez que se agrega un nuevo widget con estado en un árbol de widgets. Ahora el super.initState realiza la implementación predeterminada de la clase base de su widget. Si llama a algo antes de super.initState que depende de la clase base, esto podría causar un problema. Es por eso que se recomienda que llame a initState de esta manera:

@override
void initState() {
  super.initState();
  // DO STUFF
}
Anirudh Sharma
fuente
El razonamiento es un poco defectuoso porque disposees lo contrario. El marco espera que llame super.dispose al final , pero la recomendación es correcta.
creativecreatorormaybenot
Porque si llamas a super.dispose antes de deshacerte de las otras cosas, entonces los componentes que dependen de tu clase base pueden chocar.
Anirudh Sharma