I'm trying to figure out a good way of architecturing a Flutter app. I have several pages, which can navigate to other pages. Data modified by one page, might be used by other pages and needs to be updated. I recently started using the Provider package. I let each page have a model which implements ChangeNotifier and set a ChangeNotifierProvider above the MaterialApp. Now to update the data for other pages, i have to get the other page's model and call an update method on it. It's quite messy. I use Firestore, so i could listen to database changes, but i want to avoid too much magic. Also, sometimes it makes sense to just send data from one page to another, without using a network call, or pass data back in the Navigator.pop method. I find it hard to make good choices in how to solve this. I should probably look at a more refined architecture like redux or mobx. Or just go for a vanilla solution and use lot's of callbacks for all the various events. Those big'ol models per page, seems a bit bit bloated and messy after a while. Do anyone have a similar experience in Flutter how to architect these things? Confused
2 Answers
Using provider to apply the BLoC
pattern and combining it with RxDart is a way of solving this.
You could, for example, create an AppBloc
:
class AppBloc {
StreamController<UserInputState> _userInputController =
BehaviorSubject<UserInputState>.seeded(UserInputState('NOTHING'));
StreamSink<UserInputState> get userInputSink => _userInputController.sink;
Observable<UserInputState> get userInputObs => Observable(_userInputController.stream);
AppBloc();
}
class UserInputState {
final String input;
const UserInputState(this.input);
}
On a page you could pass data through it:
final appBloc = Provider.of<AppBloc>(context);
appBloc.userInputSink.add(UserInputState("input"));
and another page can listen to data:
final appBloc = Provider.of<AppBloc>(context);
appBloc.userInputObs.
.where((state) => state.input == "input")
.listen((state) => /* do something */);
I've simplified it here, but this can be a very robust way of handling data in a reactive way.
And the beauty is that you can bind the Observable
to a StreamBuilder (part of Flutter) to make the UI reactive too!

- 890
- 4
- 7
-
Why do you need an Observable? Can't you just get a broadcast stream that other can listen to? – Erlend Nov 22 '19 at 01:00
-
@Erlend An `Observable` is a `Stream` on steroids. It simply extends the `Stream` and adds a lot of useful functionality. More details can be found [here](https://pub.dev/documentation/rxdart/latest/rx/Observable-class.html#dart-streams-vs-observables). – voracious Nov 22 '19 at 12:42
-
Thanks. I think i will look into using streams to solve my state problem, and maybe come up with a custom solution. I will accept your answer, since my question was kind of all over the place. I also discovered the following [repo](https://github.com/christianalfoni/flutter_observable_state) and [video](https://www.youtube.com/watch?v=A7gK-VT5YsA) which i find interesting. – Erlend Nov 22 '19 at 14:43
-
1@Erlend yes, the github repo shows an interesting concept! I would normally recommend to _at least_ play around with vanilla streams/rxdart before using abstractions like the `ObservableState`. I have also wrapped around the `StreamController`, `StreamSink` and `Observable` into my own custom classes just so they become much easier to use for my own use-cases. – voracious Nov 22 '19 at 15:36
-
1Just starting using streams, dartrx and BehaviorSubject, in combination with StreamBuilder and it's so nice !! – Erlend Nov 23 '19 at 01:57
Using Provider (or any library that implements BloC pattern) and a Repository Pattern should work to move/store data locally. Basically each Bloc/Provider gets an instance of the repository and read/write values to it. Because the repository instance is the same always, you will have all yout data updated.
Also, you can use a local database like SQLite (with the sqflite package) or Hive that is a pure NoSQL database.
I personally don't like Redux, but mobx is a really good option.

- 982
- 8
- 11