I'm working on a team that is developing an app which needs to work with sensors to represent a vehicle's state. This state can either be represented through values given by external hardware sensors or work minimally through a mobile device's own sensors. And we want the ability to swap sensor packages (switch between mobile or external sensors). We also want these values to be shown asynchronously and we are researching Streams and ValueNotifiers in Flutter/Dart.
What's the best way to go (Stream vs ValueNotifier)?
A Stream is a sequence of asynchronous events. It is like an asynchronous Iterable—where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready. In other words, streams are a source of asynchronous events delivered sequentially.
There are two kinds of streams: single subscription or broadcast.
There are two types of streams in Flutter: single subscription streams and broadcast streams. Single subscription streams are the default.
ValueNotifier is a special type of class that extends Changenotifier, which can hold a single value and notifies the widgets which are listening to it whenever its holding value gets change.
ValueNotifier are very lightweight and this is why the Flutter framework uses them.
They didn't want to impose any performance penalty no matter how small if it can be avoided.
Streams are much more powerful, expecially their composability that makes it easy to use high-level functionality like the ones provided by https://pub.dartlang.org/packages/rxdart.
Using ValueNotifier in your custom code for the same performance considerations made by the Flutter team is probably premature optimization.
I'd suggest streams for business logic.
I'm going to hop in on this conversation even though I'm late to the game. I think there is a tendency for developers to overhype Streams/BLoC/RX/etc. Sure, the BLoC architecture is powerful but to me it seems to offer a lot of boilerplate compared to something like ScopedModel - essentially what appears to be a version of a ValueNotifier inside of an InheritedWidget.
The ScopedModel is nice because you can just place a widget inside of a ScopedModelDescendent (obviously this is placed within the ScopedModel) and let the value you're changing in the actual ScopeModel update the children whenever you call the notifyListeners() method. Or you can use it as a way to grab some simple data or call a function by using the .of(context) -- which is more expensive since it travels up the widget tree to find the ScopedModel, so I use that for things like sending alerts or initializing a component that needs data from within the scope before calling build.
Though, take my advice with a grain of salt. I'm just a noob with an opinion. Which may also help explain my disdain for Streams/BLoC. I really just like simpler solutions rather than the more powerful ones. If I need more power for a situation then I tend to just build out a custom solution. Just like in all things, there is a use case for each of these patterns.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With