How do you create a Stream in Dart?

2019-01-23 12:49发布

问题:

I basically know how to use them; for instance listening to the onClick Stream of an Element.

But, how do you set up your own Streams?

回答1:

Simple example

Here's a complete working example:

import 'dart:async';
import 'dart:io';

class Application {
  Stream onExit;

  Application() {
    // Create a stream controller and assign its stream to "onExit".
    var controller = new StreamController();
    onExit = controller.stream;

    // Create some class that uses our stream.
    new UserOfStream(this);

    // Whenever we exit the application, notify everyone about it first.
    controller.add('we are shutting down!');
    exit(0);
  }
}

class UserOfStream {
  UserOfStream(app) {
    app.onExit.listen((String message) => print(message));
  }
}

main() => new Application();

You can also do cool things like check if there are subscribers with controller.hasListener or you can signal an error. Be sure to check the API documentation on StreamController.

You can use new StreamController.broadcast() for allowing multiple listeners.

For copy-pasters

Here's a simple way to create a stream (great snippet for copy-pasters):

class Something {
  StreamController _onExitController = new StreamController.broadcast();
  Stream get onExit => _onExitController.stream;
}

Then the class can just access _onExitController to control the stream (to for example .add()).



回答2:

I just created a new Dart library called event_stream to make creating custom events on your classes easier. Here is an example:

class ClassWithEvents implements NotifyPropertyChanged {
  String _someProperty;

  final EventStream<PropertyChangedEventArgs> _onPropertyChangedEvent = new EventStream<PropertyChangedEventArgs>();
  Stream<PropertyChangedEventArgs> get onPropertyChanged => _onPropertyChangedEvent.stream;

  final EventStream _onClosedEvent = new EventStream();
  Stream get onClosed => _onClosedEvent.stream;

  String get someProperty => _someProperty;
  set someProperty(String value) {
    _onPropertyChangedEvent.signal(new PropertyChangedEventArgs('someProperty', value));
    _someProperty = value;
  }

  close() {
    _onClosedEvent.signal();
  }
}

main() {
  var c = new ClassWithEvents();
  c.onPropertyChanged.listen((PropertyChangedEventArgs<String> args) => print('changed: name=${args.propertyName} value=${args.value}'));
  c.onClosed.listen((_) => print('closed'));
  c.someProperty = "test";
  c.close();
}


回答3:

In addition to StreamController you can instantiate a Stream directly with one of its named constructors:

  • Stream.fromFuture() Returns a stream that fires one event (whatever the `Future' completes to.)

  • Stream.fromIterable() Returns a stream that converts the Iterable elements to a sequence of events.

  • Stream.periodic() Returns a stream that fires a computed event periodically.

This is very handy as you can write code that expects to consume a stream, but you have multiple choices as to how to feed events to that class. For example: Stream.fromIterable() could be used in a unit test to fire a known sequence of events to a class that otherwise normally would be fed data events read from a file.



标签: dart