I develop an app using BLoC pattern. In my app there are 2 routes, route A and B, and both of them access same data. A problem caused when moving the routes as below.
After moving back to route A, the StreamBuilder of showing the data never updates automatically. How can I let the StreamBuilder update on resumed state?
Here are sample codes.
routeA.dart
class RouteA extends StatefulWidget {
@override
_RouteAState createState() => _RouteAState();
}
class _RouteAState extends State<RouteA> {
@override
Widget build(BuildContext context) {
final bloc = Bloc();
return Column(
children: [
StreamBuilder( // this StreamBuilder never updates on resumed state
stream: bloc.data, // mistake, fixed. before: bloc.count
builder: (_, snapshot) => Text(
snapshot.data ?? "",
)),
RaisedButton(
child: Text("Move to route B"),
onPressed: () {
Navigator.of(context).pushNamed("routeB");
},
),
],
);
}
}
routeB.dart
class RouteB extends StatefulWidget {
@override
_RouteBState createState() => _RouteBState();
}
class _RouteBState extends State<RouteB> {
@override
Widget build(BuildContext context) {
final bloc = Bloc();
return Center(
child: RaisedButton(
child: Text("Update data"),
onPressed: () {
bloc.update.add(null);
},
),
);
}
}
bloc.dart
class Bloc {
Stream<String> data;
Sink<void> update;
Model _model;
Bloc() {
_model = Model();
final update = PublishSubject<void>();
this.update = update;
final data = BehaviorSubject<String>(seedValue: "");
this.data = data;
update.map((event) => _model.update()).listen((event) => data.sink.add(_model.getData()));
}
}
model.dart
class Model {
static Model _model;
factory Model() { // model is singleton.
_model ??= Model._();
return _model;
}
Model._();
int _data = 0;
void update() {
_data++;
}
String getData() {
return _data.toString();
}
}
StreamBuilder
updates the data whenever it gets changed not when just by calling stream
RouteA
class RouteA extends StatefulWidget {
@override
_RouteAState createState() => _RouteAState();
}
class _RouteAState extends State<RouteA> {
@override
Widget build(BuildContext context) {
return Column(
children: [
StreamBuilder( // this StreamBuilder never updates on resumed state
stream: bloc.data, // mistake, fixed. before: bloc.count
builder: (_, snapshot) => Text(
snapshot.data ?? "",
)),
RaisedButton(
child: Text("Move to route B"),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
return RouteB();
}));
},
),
],
);
}
}
Route B
class RouteB extends StatefulWidget {
@override
_RouteBState createState() => _RouteBState();
}
class _RouteBState extends State<RouteB> {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: Text("Update data"),
onPressed: () {
bloc.updateData();
},
),
);
}
}
Bloc
class Bloc {
final _update = PublishSubject<String>();
Model _model = Model();
Stream<String> get data => _update.stream;
void updateData() async {
_model.update();
_update.sink.add(_model.getData());
_update.stream.listen((event) {
print(event);
});
}
dispose() {
_update.close();
}
}
final bloc = Bloc();
just follow above changes, it will do the trick for you.