0

I'm having trouble trying to find the standard way of using the Observer Pattern in Dart; almost everything I find is very outdated or with deprecated packages.

What I'm looking for is pretty close to this answer (outdated), in which @observable is used on top of a property, and then you can listen to changes to the property (very similar to Angular in TypeScript). A similar effect can be achieved with the ChangeNotifier class but it is inside one of the Flutter packages (foundation), so I don't think this is the standard way, otherwise it would be a simple Dart package.

I've also found 2 other neat packages that do offer something close to what I'm thinking about: property_change_notifier and simple_observable.

At any rate, I wonder if there is a simple recipe to add the Observer functionality to a class property. I'm thinking about something like turning the property (actually another getter based on the property) into a Stream, which would yield a new value every time the setter on that property was called. Or have the setter take also a Stream as a parameter and have it pass a value to the Stream once the property has been changed (is it possible to append a value to a Stream externally?).

Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76

1 Answers1

4

You can use StreamView to make a class implement the stream interface – which is observable.

Here's an example:

class Counter extends StreamView<Counter> {
  Counter._(this._controller) : super(_controller.stream);
  factory Counter() => Counter._(StreamController());

  final StreamController<Counter> _controller;

  Future<void> close() => _controller.close();

  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    _controller.add(this);
  }
}

Which allows you to do:

void main() {
  final counter = Counter();
  counter.listen((value) {
    print(value.count);
  });
}
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • This looks pretty cool and flexible, but I still cannot believe that there isn't an easier standard way of dealing with this type of problem. Shouldn't this be a basic reactive feature of Dart? – Philippe Fanaro Feb 21 '20 at 18:16
  • Regarding your code, when I try `counter.increment()` multiple times in a row, it only prints the last value, e.g. 10 increments will print 10x the number 10. Shouldn't it print 0, 1, 2..., 10? i.e. each increment triggers the lambda function you passed into `listen`? – Philippe Fanaro Feb 21 '20 at 18:16
  • 1
    Make your `StreamController` sync if that's what you want – Rémi Rousselet Feb 21 '20 at 19:15
  • For me to improve, what was the reason for rejecting my edit suggestion? – Philippe Fanaro Feb 22 '20 at 20:38