Patrón BLoC con un ejemplo simple

Y nuevamente sobre BLoC usando el clásico ejemplo de contador Flutter.


Al leer algunos artículos sobre programación reactiva y usar el patrón BLoC en aplicaciones, me di cuenta de que no me estaba poniendo al día con algo. Como de costumbre, no hay suficiente tiempo para todo, pero ahora, había una hora libre y hay fuerza - decidida, escribiré la aplicación Flutter más simple con el patrón BLoC.


Debajo de las aplicaciones y explicaciones de animashka de gato, por qué lo escribí de esa manera. Muy interesante es la opinión de la comunidad.


imagen


Sí, ya hemos escrito sobre este patrón muchas veces, pero de todos modos, no hay instrucciones claras y reglas de aplicación, y a menudo surge la pregunta de cómo implementar correctamente la lógica en la aplicación.


El propósito del artículo es aportar un poco de claridad a mí mismo y, espero, a los lectores.


Entonces, la definición del patrón, como lo expresaron los ingenieros de Google, BLOC es una clase simple en la que:


  1. todos los flujos de salidas
  2. todas las entradas son corrientes
  3. esta clase debería eliminar la lógica de la interfaz visual

Para implementar este patrón, si es necesario, podemos usar la biblioteca rxdart , pero no podemos usarla.


Esto no eliminará la reactividad como podría pensar. A medida que los creadores del paquete escriben, rxdart agrega funcionalidad a las características ricas ya incorporadas del lenguaje Dart al trabajar con flujos.


App



Entonces, tomamos la aplicación con contadores, que se crean automáticamente cuando se crea el proyecto e intentamos reescribirla usando el patrón BLoC.


Tareas


  1. Eliminar toda la lógica de los widgets
  2. En la clase BLoC, reciba solo secuencias de entrada y solo secuencias de salida. Por ejemplo, la función propuesta en los comentarios al artículo .

imagen


no nos conviene, ya que viola la regla de pasar solo transmisiones a la clase.


Solución:


  1. Eliminamos toda la lógica de los widgets. Hacemos la clase Stateless y dejamos de actualizar el estado con setState.
  2. Mostramos las lecturas del medidor en diferentes lugares usando el widget incorporado, que está hecho específicamente para mostrar datos de flujos: StreamBuilder.

class MyHomePage extends StatelessWidget { CounterBloc counterBloc = CounterBloc(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: StreamBuilder<int>( stream: counterBloc.pressedCount, builder: (context, snapshot) { return Text( 'Flutter Counter Bloc Example - ${snapshot.data.toString()}', ); }), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), StreamBuilder<int>( stream: counterBloc.pressedCount, builder: (context, snapshot) { return Text( '${snapshot.data.toString()}', style: Theme.of(context).textTheme.display1, ); }), ], ), ), floatingActionButton: Container( width: 100.0, height: 100.0, child: FloatingActionButton( onPressed: () { counterBloc.incrementCounter.add(null); }, tooltip: 'Increment', child: Text( "+ \n send \n to BLoC", textAlign: TextAlign.center, ), ), ), ); } } 

  1. Creamos una clase separada donde implementamos el patrón BLoC:
    3.1 Todas las propiedades y métodos de clase están ocultos.
    3.2 Para recibir y transferir el estado, utilizamos transmisiones que son visibles desde el exterior mediante captadores (pero aquí hay un artículo interesante sobre ellos ).

 class CounterBloc { int _counter; CounterBloc() { _counter = 1; _actionController.stream.listen(_increaseStream); } final _counterStream = BehaviorSubject<int>.seeded(1); Stream get pressedCount => _counterStream.stream; Sink get _addValue => _counterStream.sink; StreamController _actionController = StreamController(); StreamSink get incrementCounter => _actionController.sink; void _increaseStream(data) { _counter += 1; _addValue.add(_counter); } void dispose() { _counterStream.close(); _actionController.close(); } } 

Eso es todo, tenemos un ejemplo de trabajo, en el que transmitimos y recibimos el estado en flujos y mostramos datos en los widgets necesarios sin aplicar ninguna lógica en la parte visual.


Por lo tanto, podemos separar todos los cálculos, transferencias de datos, etc. desde la interfaz. Por ejemplo, si agrega diferentes etiquetas al contador dependiendo de la cantidad y las toma de una base de datos externa, toda esta lógica ya pasará por BLoC; nuestra interfaz no sabrá nada al respecto.


Nota 1: tenga en cuenta que estamos creando una instancia de la clase> CounterBloc counterBloc = CounterBloc (); y luego obtenemos datos de él. Si necesitamos estos datos en diferentes pantallas (en clases espaciadas), entonces podemos usar widgets heredados para la transferencia o hacer Singleton de nuestra clase.


Código de ejemplo de Github


Buena codificación para todos!


Continuación


En la secuela, transferimos el estado en diferentes pantallas, guardamos los datos en la memoria permanente del teléfono, probamos BLoC https://habr.com/en/post/485002/

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


All Articles