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();
}
}