Los estados
Introducción
La gestión de estados es un punto fundamental. En los diversos ejemplos cubiertos hasta ahora y en los que quedan por venir, hay dos herencias recurrentes, StatelessWidget y StatefulWidget. Le permiten definir el comportamiento de clases o widgets. La pregunta es saber si necesitarán que su estado cambie con el tiempo o no.
Esta gestión de los estados que se encuentra en StatefulWidget, es realmente práctica, pero tiene un punto débil innegable. La parte gráfica de la aplicación está estrechamente vinculada a la parte lógica. Esto dificulta el mantenimiento de una aplicación. La forma correcta de proceder es lograr reducir este acoplamiento tanto como sea posible. Sobre este tema, que sigue siendo muy amplio y sobre el que la posición de los desarrolladores sigue sin estar clara, la opción aquí es centrarse en dos métodos muy extendidos y reconocidos, aunque existen otros. Inicialmente, se abordarán los providers. Hoy, según los equipos de Flutter, son la ruta preferida. Sin embargo, la comunidad sigue estando muy atraída por el pattern BLoC. Así que este es un tema que también se debe abordar.
Por supuesto, estos temas son muy complejos. Este capítulo solo se puede considerar como un primer acercamiento. De hecho, si tuviéramos que entrar en detalles y descubrir todas las prácticas...
StatelessWidget
El StatelessWidget es una clase (un widget) que se utiliza para crear una interfaz de usuario. Como indica su nombre, su vocación no es hacer evolucionar su estado con el tiempo.
Una clase que implementa StatelessWidget, debe incluir un widget build:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return null;
}
}
Este build se llama varias veces. En primer lugar, cuando el widget se inserta en el árbol de widgets, cuando se modifica su padre o cuando se asocia con otro widget InheritedWidget.
Las dos últimas llamadas, que pueden ocurrir con regularidad, obligarán al widget a reconstruirse, disminuyendo así el rendimiento de la aplicación. Sin embargo, hay varios puntos a tener en cuenta para minimizar este fenómeno.
El primer método consiste, si el contexto lo permite, en minimizar el número de widgets que contiene. En particular, si solo se debe colocar un elemento, es aconsejable evitar el uso de Row, Column, Padding y SizedBox. En este caso, será preferible utilizar Align o CustomChildLayout. Asimismo, en lugar de anidar varias capas de Container (con su Decoration) para obtener un efecto gráfico particular, sería mejor optar por un simple CustomPaintWidget.
Siempre que sea posible...
StatefulWidget
El StatefulWidget es, al contrario de lo que sucede con StatelessWidget, un widget que pretende hacer evolucionar su estado con el tiempo.
Por tanto, su construcción es un poco diferente y se lleva a cabo a través de dos clases. La primera, clásico, extiende StatefulWidget. Tiene un papel bastante declarativo. Entonces es una clase que contendrá un constructor y atributos, por ejemplo. También contiene, y es obligatorio, la llamada al método createState. Este último devolverá una instancia de una clase que administra el State llamando a su constructor. Se ocupará de dos cosas. En primer lugar, describirá los widgets, principalmente elementos gráficos. En segundo lugar, podrá hacerlos cambiar y evolucionar utilizando un método setState.
Aquí hay un ejemplo de una clase extendida StatefulWidget:
class Inicio extends StatefulWidget {
Inicio({Key key, this.title, this.color}) : super(key: key);
final String title;
Color color;
@override
State<StatefulWidget> createState() {
return _InicioState();
}
}
Se trata de una construcción bastante clásica. Sin embargo, el método createState se puede optimizar y es preferible encontrarlo bajo esta sintaxis:
@override
_InicioState createState() => _InicioState();
En cuanto a la clase _InicioState, deberá soportar la carga de la parte gráfica, así como su evolución potencial a través de setState. Para ofrecer otro ejemplo que normalmente se da con la aplicación por defecto, se propone una variante. Esta vez, presionar FloatingActionButton va a modificar aleatoriamente el color de varios elementos en la pantalla.
Esta clase debe extender State <T>. T se corresponde con la clase asociada que extiende StatefulWidget. En el ejemplo, T será reemplazado por Inicio.
class _InicioState extends State <Inicio>...
Interfaz y acoplamiento lógico
El ciclo de vida de los StatefulWidget es complejo, pero ofrece muchas posibilidades. En particular, los métodos setState, que son extremadamente prácticos, como han demostrado las diversas demostraciones.
Sin embargo, sigue existiendo un problema importante. La inclusión de un setState que incluye la lógica de la aplicación dentro de la misma interfaz gráfica, hace que la aplicación sea difícil de mantener. Además, dado que un setState está vinculado a un contexto (context), no es posible actualizar varias interfaces al mismo tiempo.
En general, en programación, la buena práctica consiste en separar la parte lógica de la gestión gráfica. En cuanto a Flutter, existen muchos métodos que permiten implementar esta separación. Sin ser exhaustivos, aquí hay algunos:
-
Provider
-
BLoC
-
InheritedWidget
-
ScopedModel
-
Redux
-
MobX
-
…
Por tanto, la elección es difícil y el debate no ha terminado. Debemos ser conscientes de que se trata de conceptos avanzados, que harían necesario un libro por sí solos si se tuvieran que estudiar en detalle.
Sin embargo, en la lista anterior, todavía hay dos prácticas que destacan: los providers y los BLoC. Las siguientes secciones no entrarán en detalles, pero proporcionarán una comprensión de los conceptos básicos.
Para ello, la demostración de lanzamiento (el contador) se volverá a trabajar con ambos métodos. Tiene la ventaja de ser simple y lo más importante, ya ha sido manipulado muchas veces.
1. Provider
Los providers se pueden considerar como la práctica de referencia. De hecho, en la conferencia Google IO de 2019, este fue el camino que se consideró como preferido.
¿Por qué?
Las razones son simples: funciona muy bien y el enfoque es más fácil que con otros métodos.
Por tanto, la ventaja será poder trabajar con StatelessWidget. No habrá gestión de estado en la parte gráfica de la aplicación.
Por lo tanto, la parte lógica se externaliza y se puede volver a utilizar en cualquier otro lugar del programa, si fuera necesario.
Por tanto, el acoplamiento entre la interfaz y la lógica de la aplicación es débil.
Para facilitar su implementación, Google...