Simplificando la gestión de estado con Bloc en Flutter

Lograr un código más limpio en Flutter con Bloc

Eduardo CQ
Comunidad Flutter
8 min readApr 20, 2020

--

Hola amigos, luego de un tiempo de no hacer una traducción para la comunidad de Flutter en español, les traigo un nuevo artículo escrito por Dhananjay Trivedi, que puedes encontrar el artículo original aquí.

Si ha estado desarrollando aplicaciones Flutter, sabe que es crucial administrar el estado de su aplicación de la mejor manera posible.

Flutter nos brinda muchas opciones de administración de estado, como Provider, Bloc, Redux y MobX.

Hoy, verás a Bloc.

Entiendo que puede ser un poco más difícil de entender, también lo fue para mí. Pero ahora creo que lo entiendo, así que estoy aquí para simplificartelo.

Sabes que en Flutter es muy fácil mezclar su lógica de UI con la lógica de su negocio, que no es realmente la mejor manera de desarrollar aplicaciones que se puedan mantener.

Bloc viene al rescate al dar una mejor estructura a tú aplicación, al separar la interfaz de usuario y la lógica de negocios de tú aplicación. Pero antes de comenzar a implementarlo, primero debes comprender …

El artículo va a ser un poco largo, pero como principiante, se te irá aclarando el uso de Bloc al final.

¿Qué es Bloc de todos modos?

Bloc significa lógica de negocio y componente. Es como un recuadro negro que envuelve toda su lógica de negocios (y componentes relacionados) y asigna varios eventos de aplicaciones a estados de aplicaciones.

Si esa definición fue demasiado técnica para ti, trata de entenderla mejor con algunos ejemplos.

Si estás usando una aplicación meteorológica:

Habrá varios eventos en su aplicación, como getWeather() setLocation(), y resetWeather()eso se activará con las acciones del usuario o alguna lógica interna de su aplicación.

Estas acciones actualizarán la interfaz de usuario de su aplicación con un nuevo estado en consecuencia después de que la operación se realice con éxito.

Otro ejemplo: la aplicación de contador Flutter predeterminada

Aquí solo hay un evento, y ese es el incrementCounterque genera el nuevo estado, que muestra el valor incrementado del contador.

bloc es el cuadro negro que le dirá qué operación debe realizarse en qué evento y luego qué estado debe generarse después de que se complete la operación.

¿Cómo se define el bloque para su aplicación?

Hay un pequeño precio a pagar

Un inconveniente importante de Bloc es la cantidad de código repetitivo que tienes que escribir, incluso para los cambios más pequeños de la interfaz de usuario.

Ese es el único inconveniente que he visto hasta ahora, pero ciertamente simplifica el código de su aplicación al separar toda la lógica de la interfaz de usuario de la lógica de negocios.

Por lo tanto, puede tomar todo el código repetitivo como una inversión requerida para mantener su código fácil de mantener y comprender con Bloc.

Esto es lo que obtienes

Por ejemplo, supongamos que está creando una aplicación meteorológica con Bloc. Has definido todos sus eventos, estados y su aplicación funciona perfectamente.

Ahora, si tienes que agregar otra función dentro de la misma pantalla, puedes simplemente seguir adelante y definir un nuevo evento y un nuevo estado dentro de su bloccon un poco de lógica sobre cómo asignar el nuevo evento a un nuevo estado.

Ya terminaste! No tienes que tocar / perturbar otros eventos y estados creados, y simplemente puede agregar su nuevo conjunto de características sin mucho problema.

Esto es similar a lo que el principio abierto-cerrado de los principios SOLID le dicen que hagas.

Lo que estaremos construyendo

Desarrollarás una versión modificada de la aplicación de contador, que te ayudará a obtener una imagen más clara de bloc.

Habrá cuatro botones:

  • Incremento del valor del contador: actualiza instantáneamente el valor del contador
  • Disminuir el valor del contador: actualiza instantáneamente el valor del contador
  • Generar valor aleatorio: simularemos cierto retraso y luego actualizaremos el valor

Si entendió los requisitos, puedes ver que lo que se ha resaltado anteriormente son eventos, y la explicación a la derecha del colon son los estados.

1. Agregue estas dependencias a su pubspec.yaml

A partir de marzo de 2020, estoy agregando esta dependencia para Flutter.

bloces la biblioteca creada por el equipo bloclibrary.dev, y proporciona los fundamentos básicos del patrón bloc. Pero es un poco más complejo; por lo tanto, obtienes flutter_bloccreado por el mismo equipo para facilitar las cosas a los desarrolladores de Flutter.

Gracias equipo!

2. Crea tu clase ‘Bloc’

Mi código de UI estará en el CounterScreen, dentro del archivo counter_screen.dart.
(Llegaremos a la parte de la interfaz de usuario más adelante).

Cree un nuevo archivo Dart para su clase bloc con el nombre counter_screen_bloc.dart. Definirás este archivo de clase bloc.

Dentro de la pantalla bloc, definiremos tres cosas:

  • Evento: para mostrar todos los eventos posibles
  • Estado: para mostrar todos los estados posibles
  • Bloque: cómo asignar esos eventos a estados

Estas son las declaraciones de importación requeridas para los próximos pasos.

3. Definir eventos

Dentro del archivo de clase en blanco bloc , comience definiendo un evento.

He nombrado él CounterScreenEvent.

Equatablehace que nuestras clases sean equiparables / comparables, lo cual es necesario para la lógica de mapeo dentro de la clase bloc.

Equatablele pide que anule el get propsque hemos hecho aquí.

4. Definir estados

Debajo de estos, definamos los estados a los que se asignará cada uno de estos.

¿Por qué, solo dos estados?

Bueno, el usuario verá los valores de contador incrementados / decrementados en la pantalla, o verá una pantalla de carga mientras intentamos generar un número aleatorio que simule una llamada de red.

El ShowCounterValueestado tendrá un valor de contador asociado. Por lo tanto, definimos una propiedad en esa clase llamada counterValuepara ayudarlo a pasar el valor del contador a la interfaz de usuario de la aplicación desde Bloc.

5. Finalmente, defina nuestro ‘Bloc’

Sí, finalmente podemos definir nuestro bloc.

  • En la primera línea, tienes DashboardScreenBloc, que se extiende Bloc<Event,State>como has definido anteriormente
  • Defines una propiedad para el valor de contador llamado counterValue, que se utilizará para mantener el estado de nuestro contador
  • Ahora tienes que definir initialState. Cuando el bloccarga, el estado inicial y se establecerá en ShowCounterValue(counterValue).
  • Finalmente, tienes una función mapEventToState(que hace exactamente lo que significa el nombre). Si observa la función, verá que está marcada como async*.

Sólo para mantener a todos en la misma página, voy a explicar
asyncvs async*.

Si su función devuelve un valor futuro después de realizar una determinada operación, marcamos esa función como async. Estas funciones devuelven un valor solo una vez, y su ejecución termina con la instrucción return.

La función marcada como async*, por otro lado, devuelve una secuencia. Esta función produce valores diferentes y no solo los devuelve. Su ejecución aún continúa, y pueden producir tantos valores como desee.

Es por eso que su salida se llama transmisión.

Terminemos nuestro blocmapeando eventos a estados.

A continuación se muestra el código completo de counter_screen_bloc.dart.

Una cosa importante a saber en bloc, es que si nextState == currentStateevalúa true, bloc ignora la transición de estado.

Si no extiende su clase de estado como Equatable, todos los estados desde los que yield llamará serán tratados como únicos.

Si eso se ajusta a sus requisitos, no debería molestarse mucho, pero si existe la posibilidad de que se repitan estados uno tras otro, ¿por qué desperdiciar su rendimiento en la reconstrucción del mismo estado?

Por lo tanto, ampliamos Equatabley anulamos el método props.

Si no se anula el método props, blocno sabrá cómo comparar las dos clases de estado y probablemente las tratará de la misma manera. Por lo tanto, no vería que se activara el nuevo estado.

6. Trabajemos en esa interfaz de usuario

Comenzando con main.dart

Como estamos usando un bloc de nombre CounterScreenBlocen nuestra interfaz de usuario con nombre CounterScreen, usamos BlocProvider y definimos qué se debe proporcionar con qué bloc.

Aquí está el main.dartcódigo completo .

Miremos adentro 'counter_screen.dart’

Dentro de la buildfunción de nuestro CounterScreen, tenemos que inicializar el bloc. Del mismo modo, dentro de la función de disposición, tenemos que cerrar nuestro blocpara evitar pérdidas de memoria.

Es una buena práctica disponer del bloque en la función dispose () del mismo widget cuyo build () puede haberse utilizado para inicializar el bloque.

Aquí está el completo counter_screen.dart:

¡Eso es! Deberías tener un proyecto funcional.

Aquí está el código para el proyecto completo:

Conclusión

¡Eso es! Eso es todo lo que debes saber para crear una aplicación Flutter con código limpio, todo gracias a Bloc.

Nuevamente, el código repetitivo que ve es una inversión para mantener su código mantenible.

También debido a esto, no recomendaría que lo aplique en todas las pantallas, solo donde hay muchos estados diferentes involucrados.

De lo contrario, Provider es otra gran solución de administración de estado para funciones más simples en su aplicación.

--

--