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 esperarSi 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 imagenEste 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.