Administrar el estado de la aplicación en Flutter

Hola Habr! Al presentar una traducción del artículo, Permítame ayudarlo a comprender y elegir una solución de administración estatal para su aplicación , lo que me llamó la atención y se interesó en el proceso de aprender los conceptos básicos de la administración estatal en Flutter. Estaré encantado de escuchar cualquier crítica con respecto a esta traducción. En las comillas (``) se escribirán mis pensamientos y explicaciones personales.


La gestión del estado del aleteo es un tema candente. Hay muchas soluciones posibles para el problema, y ​​confundirse con ellas, elegir la más adecuada para sus necesidades es extremadamente simple. Yo mismo estaba confundido, pero encontré una solución adecuada. Déjame compartirlo contigo.

Para encontrar una solución que se adapte a sus necesidades, debe determinar las propias necesidades. En mi caso, esto es:

  • Tener la oportunidad de desarrollar el proyecto sin comprometer la calidad del código.
  • Separe la lógica de visualización de la lógica de negocios
  • Tener un código claro que sea difícil de descifrar
  • Código de previsibilidad y comprensibilidad

Dados estos requisitos, quedan opciones adecuadas:

  • Uso del setState() y widgets con estado
  • `Biblioteca` ScopedModel
  • Uso del patrón BLoC (componentes de lógica de negocios)
  • Redux

La diferencia entre estado local y global


Antes de sumergirse en el análisis de las soluciones seleccionadas, debe comprender la diferencia entre el estado local y global. Un ejemplo práctico es adecuado para esto:
Imagine un formulario de autorización, en el que se le solicita al usuario que ingrese un nombre de usuario y contraseña y obtenga el objeto "identidad de usuario" después de enviar el formulario. En este ejemplo, cualquier verificación de los datos ingresados ​​en los campos del formulario formará parte del estado local del `widget de formulario de autorización`, y el resto de la aplicación no debería saberlo. Y el objeto de "identidad" devuelto por el "servidor de autorización" es parte del estado global. Por lo tanto, otros componentes dependen de este objeto, cambiando el comportamiento dependiendo de si el usuario está autorizado.

Breves conclusiones para quienes están cansados ​​de esperar
Si no quiere esperar o no está interesado en mi investigación, aquí hay una breve descripción de los resultados:


Mi recomendación es utilizar BLoC para la administración del estado local y Redux para el estado global, especialmente si está creando una aplicación compleja que crecerá con el tiempo.


Por qué no deberías usar setState ()


Usar setState() dentro de sus widgets es excelente para setState() prototipos rápidamente y obtener comentarios sobre estos cambios, pero de esta manera no nos ayuda a lograr nuestros objetivos, porque la lógica de visualización se mezcla con la lógica de negocios, lo que viola el principio de limpieza y calidad del código. El mantenimiento de dicho código será difícil en el futuro, por lo tanto, a excepción de la creación de prototipos, no se recomienda este enfoque.

ScopedModel: un paso en la dirección correcta


ScopedModel es una biblioteca de terceros de Brian Egan . Permite crear objetos de Models especiales, así como utilizar el método notifyListeners() cuando sea necesario. Por ejemplo, para realizar un seguimiento de cualquier cambio en las propiedades de un objeto modelo:

 class CounterModel extends Model { int _counter = 0; int get counter = _counter; void increment() { _counter++; notifyListeners(); } } 

En nuestros widgets, podremos responder a los cambios en el modelo utilizando el widget ScopedModelDescendant `provisto por esta biblioteca ScopedModelDescendant :

 class CounterApp extends StatelessWidget { @override Widget build(BuildContext context) { return new ScopedModel<CounterModel>( model: new CounterModel(), child: new Column(children: [ new ScopedModelDescendant<CounterModel>( builder: (context, child, model) => new Text('${model.counter}'), ), new Text(" ,     CounterModel") ]) ); } } 

A diferencia del uso del enfoque setState() , esta solución le permite separar la lógica de visualización de la lógica de negocios. Sin embargo, impone ciertas restricciones:

  • Si el Model vuelve complejo, se hace difícil determinar cuándo usar el método notifyListeners() y cuándo no evitar una actualización innecesaria de la interfaz
  • La API proporcionada por Model , en general, no describe con precisión la naturaleza asincrónica de la interfaz de la aplicación

Dado todo esto, si el estado de su aplicación no es fácil de administrar, no recomiendo usar este enfoque de datos. Simplemente no creo que sea capaz de proporcionar productivamente el crecimiento y la complejidad de las aplicaciones.

Potente solución - BLoC


Este patrón fue inventado por Google y también se usa allí. Nos ayudará a alcanzar los siguientes objetivos:

  • Separación de la lógica de visualización de la lógica de negocios
  • Usar la naturaleza asincrónica para mostrar una interfaz
  • La capacidad de reutilizar en diferentes aplicaciones de Dart, como Flutter o AngularDart

La idea detrás de este enfoque es muy simple:

  • BLoC utiliza
     Sink<T> 
    Api para describir el ingreso asincrónico de nuestros componentes de datos
  • BLoC utiliza
     Stream<T> 
    Api para describir datos devueltos asincrónicamente por nuestros componentes
  • Finalmente, podemos usar el widget StreamBuilder para controlar los flujos de datos, sin StreamBuilder ningún esfuerzo por nuestra parte para suscribirnos a actualizaciones de datos y volver a dibujar widgets

Google tiene buenos ejemplos de uso de este patrón de administración de estado porque es ampliamente utilizado y altamente recomendado por la compañía.

Yo mismo recomiendo utilizar este enfoque para administrar el estado local, pero incluso es adecuado para administrar el estado global. Sin embargo, en el último caso, encontrará un problema: dónde y cómo implementar BLoC correctamente para que diferentes componentes tengan acceso a él, y luego Redux ingresa a la escena.

Redux y BLoC: la combinación perfecta para mí


Uno de los objetivos que describí al comienzo del artículo fue encontrar algo que sea ampliamente utilizado y predecible, y este es Redux, un patrón y un conjunto de herramientas que, en conjunto, nos ayudan a administrar el estado global. Tiene tres principios básicos en el núcleo:

La única fuente de verdad es que todo el estado del state su aplicación se almacena en un objeto de árbol en una sola store

  • El estado es de solo lectura: la única forma de cambiar el estado es llamar a un objeto de acción especial que describa lo que debería pasarle al estado
  • Los cambios se realizan utilizando funciones puras: para determinar qué cambios en el estado, se escribe la función pura ` reducer , que no debería causar ningún efecto secundario` Enlace al código de muestra`


Enlace a la publicación original, de donde proviene la imagen

Este enfoque para administrar el estado es ampliamente aceptado por los desarrolladores web, y su aparición en dispositivos móviles ayudará a beneficiar a los desarrolladores web y de aplicaciones móviles.

Brian Egan está desarrollando tanto el Redux original como flutter_redux , y también creó una increíble aplicación de Todo en la que aplicó muchos patrones arquitectónicos, incluido Redux.
Dadas todas las cualidades de Redux, recomiendo usarlo para administrar el estado global, pero debe asegurarse de no usarlo para administrar el estado local si desea escalar su aplicación.

Ultimas palabras


No hay una solución completamente correcta o incorrecta en este artículo. Para decidir qué enfoque aplicar en su proyecto, debe decidir sobre sus necesidades. Para mí y mis objetivos, la combinación de Redux y BLoC permite que mis proyectos crezcan de forma rápida y segura, y también facilita que los desarrolladores externos puedan ingresar a estos proyectos, gracias a herramientas accesibles y claras. Sin embargo, no todos tienen las mismas necesidades y, con el tiempo, puede encontrar problemas `en las herramientas actuales 'e incluso mejores soluciones. Es muy importante permanecer siempre curioso, aprender y pensar si esta o aquella herramienta es adecuada para usted.

Source: https://habr.com/ru/post/es435780/


All Articles