Dart: Streams vs ValueNotifiers
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.
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.