StatefulWidget vs StatelessWidget.
StatelessWidget : un widget que no requiere un estado mutable.
Un widget sin estado es un widget que describe parte de la interfaz de usuario mediante la construcción de una constelación de otros widgets que describen la interfaz de usuario de manera más concreta. El proceso de construcción continúa de forma recursiva hasta que la descripción de la interfaz de usuario es completamente concreta (por ejemplo, consiste enteramente en RenderObjectWidgets, que describen RenderObjects concretos).
El stateless
widget es útil cuando la parte de la interfaz de usuario que está describiendo no depende de nada más que la información de configuración en el propio objeto y el
BuildContext en el que se infla el widget. Para composiciones que pueden cambiar dinámicamente, por ejemplo, debido a que tienen un estado controlado por reloj interno, o dependiendo de algún estado del sistema, considere usar
StatefulWidget
.
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
StatefulWidget : un widget que tiene un estado mutable.
- Los widgets con estado son útiles cuando la parte de la interfaz de usuario que está describiendo puede cambiar de forma dinámica.
Cuando Flutter construye un StatefulWidget
, crea un objeto State. Este objeto es donde se guarda todo el estado mutable de ese widget.
El concepto de estado se define por dos cosas:
1) Los datos utilizados por el widget pueden cambiar.
2) Los datos no se pueden leer de forma sincrónica cuando se crea el widget. (Todos los estados deben estar establecidos en el momento en que se llama al método de construcción).
Ciclo de vida de StatefulWidget
El ciclo de vida tiene los siguientes pasos simplificados:
- createState () : cuando se le indica a Flutter que cree un StatefulWidget, llama inmediatamente
createState()
.
@override
_MyState createState() => _MyState();
- montado == verdadero : todos los widgets tienen una
this.mounted
propiedad bool . Se vuelve verdadero cuando buildContext
se asigna. Es un error llamar setState
cuando se desmonta un widget. Si este objeto de estado se encuentra actualmente en un árbol.
Después de crear un objeto State y antes de llamar initState
, el marco "monta" el objeto State asociándolo con un
BuildContext
. El objeto State permanece montado hasta que el marco
llama dispose()
, después de lo cual el marco nunca le pedirá al
objeto State que vuelva a construir.
Es un error llamar a setState a menos que mount sea verdadero.
bool get mounted => _element != null;
- initState () : este es el primer método que se llama cuando se crea el widget (después del constructor de la clase, por supuesto).
initState
se llama una vez y solo una vez. Debe llamarsuper.initState().
Inicialice los datos que se basan en el BuildContext específico para la instancia creada del widget.
Inicialice las propiedades que dependen de estos widgets 'padre' en el árbol.
Suscríbase a Streams, ChangeNotifiers
o cualquier otro objeto que pueda cambiar los datos de este widget.
@override
initState() {
super.initState();
cartItemStream.listen((data) {
_updateWidget(data);
});
}
- didChangeDependencies () : se llama cuando cambia una dependencia de este objeto de estado.
Este método también se llama inmediatamente después initState
. Es seguro llamar BuildContext.inheritFromWidgetOfExactType
desde este método.
Las subclases rara vez anulan este método porque el marco siempre llama a build después de cambios de dependencia. Algunas subclases anulan este método porque necesitan hacer un trabajo costoso (por ejemplo, búsquedas de red) cuando cambian sus dependencias, y ese trabajo sería demasiado costoso para cada compilación.
@protected
@mustCallSuper
void didChangeDependencies() { }
- build () : describe la parte de la interfaz de usuario representada por el widget.
El marco llama a este método en varias situaciones diferentes:
- Después de llamar
initState
.
- Después de llamar
didUpdateWidget
.
- Después de recibir una llamada a
setState
.
- Después de que cambie una dependencia de este objeto de estado (por ejemplo, un InheritedWidget al que hace referencia los cambios de compilación anterior).
- Después de llamar a deactivate y luego reinsertar el objeto State en el árbol en otra ubicación.
El marco reemplaza el subárbol debajo de este widget con el widget devuelto por este método, ya sea actualizando el subárbol existente o eliminando el subárbol e inflando un nuevo subárbol, dependiendo de si el widget devuelto por este método puede actualizar la raíz del subárbol existente. , según lo determinado llamando
Widget.canUpdate
.
Normalmente, las implementaciones devuelven una constelación de widgets recién creada que se configura con información del constructor de este widget, el BuildContext dado y el estado interno de este objeto State.
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
- didUpdateWidget () : se llama cada vez que cambia la configuración del widget.
Si el widget principal se reconstruye y solicita que esta ubicación en el árbol se actualice para mostrar un nuevo widget con el mismo tipo de tiempo de ejecución y Widget.key, el marco actualizará la propiedad del widget de este objeto State para hacer referencia al nuevo widget y luego llamar a esto método con el widget anterior como argumento.
Anule este método para responder cuando cambie el widget (por ejemplo, para iniciar animaciones implícitas).
El marco siempre llama a build después de llamar a didUpdateWidget, lo que significa que cualquier llamada a setState en didUpdateWidget es redundante.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
- setState () : siempre que cambie el estado interno de un objeto State, realice el cambio en una función a la que pase
setState
:
Llamar a setState notifica al marco que el estado interno de este objeto ha cambiado de una manera que podría afectar la interfaz de usuario en este subárbol, lo que hace que el marco programe una compilación para
este objeto de estado.
Si simplemente cambia el estado directamente sin llamar a setState , es posible que el marco no programe una compilación y que la interfaz de usuario de este subárbol no se actualice para reflejar el nuevo estado.
setState(() { _myState = newValue });
- deactivate () : se llama a Deactivate cuando se elimina el estado del árbol, pero podría reinsertarse antes de que finalice el cambio de marco actual. Este método existe básicamente porque los objetos de estado se pueden mover de un punto a otro en un árbol.
- El marco llama a este método cada vez que elimina este objeto State del árbol. En algunos casos, el marco reinsertará el objeto de estado en otra parte del árbol (por ejemplo, si el subárbol que contiene este objeto de estado se injerta de una ubicación en el árbol a otra). Si eso sucede, el marco se asegurará de que llame a build para darle al objeto State la oportunidad de adaptarse a su nueva ubicación en el árbol. Si el marco vuelve a insertar este subárbol, lo hará antes del final del fotograma de animación en el que se eliminó el subárbol del árbol. Por esta razón, los objetos de estado pueden posponer la liberación de la mayoría de los recursos hasta que el marco llame a su método de disposición.
Rara vez se usa.
@protected
@mustCallSuper
void deactivate() { }
- dispose () : se llama cuando este objeto se elimina del árbol de forma permanente.
El marco llama a este método cuando este objeto State nunca se volverá a compilar. Después de las llamadas al marco dispose()
, el objeto State se considera desmontado y la propiedad montada es falsa. Es un error llamar a setState en este punto. Esta etapa del ciclo de vida es terminal: no hay forma de volver a montar un objeto de estado que se ha eliminado.
Las subclases deben anular este método para liberar cualquier recurso retenido por este objeto (por ejemplo, detener cualquier animación activa).
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}
Para obtener más información, vaya aquí aquí , aquí