Bloc Usage Without RxDart in Flutter
16-03-2020Events
abstract class CounterEvent {} class IncrementEvent extends CounterEvent{} class DecrementEvent extends CounterEvent{}
Bloc Class
import 'dart:async'; import 'package:fluttertemplate/blocs/bloc.dart'; import 'counter_event.dart'; /// More Detail: /// https://www.didierboelens.com/2018/08/reactive-programming-streams-bloc/ /// https://pub.dev/documentation/rxdart/latest/ /// https://blog.soshace.com/understanding-flutter-bloc-pattern/ class CounterBloc extends Bloc { int _counter = 0; final _counterStateController = StreamController<int>(); Stream<int> get counterStream => _counterStateController.stream; final _counterEventController = StreamController<CounterEvent>(); Sink<CounterEvent> get counterEventSink => _counterEventController.sink; CounterBloc() { _counterEventController.stream //.where((value) => value == IncrementEvent())//where clause :) .listen(_mapEventToState); } void _mapEventToState(CounterEvent event) { if (event is IncrementEvent) _counter++; else _counter--; _counterStateController.sink.add(_counter); } @override void dispose() { _counterStateController.close(); _counterEventController.close(); } }
Usage
class _MyHomePageState extends State<MyHomePage> { final _bloc = new CounterBloc(); @override Widget build(BuildContext context) { // This method is rerun every time setState is called, for instance as done // by the _incrementCounter method above. // // The Flutter framework has been optimized to make rerunning build methods // fast, so that you can just rebuild anything that needs updating rather // than having to individually change instances of widgets. return Scaffold( appBar: AppBar( // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. title: Text(widget.title), ), body: Center( // Center is a layout widget. It takes a single child and positions it // in the middle of the parent. child: StreamBuilder( stream: _bloc.counterStream, builder: (BuildContext context, AsyncSnapshot<int> snapshot) { if(!snapshot.hasData){ return Center(child: CircularProgressIndicator(),); } return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[Text('${snapshot.data}')], ); }, )), floatingActionButton: FloatingActionButton( onPressed: () => _bloc.counterEventSink.add(IncrementEvent()), tooltip: 'Increment', child: Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } @override void dispose() { _bloc.dispose(); super.dispose(); } }