Reputation: 1322
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?
Upvotes: 45
Views: 32950
Reputation: 18464
There is sample with from flutter bloc
Add dependency
rxdart: ^0.27.2
Create stream controller
final _todoStreamController = BehaviorSubject<List>.seeded(const []);
Future saveTodo(Todo todo) { final todos = [..._todoStreamController.value]; final todoIndex = todos.indexWhere((t) => t.id == todo.id); if (todoIndex >= 0) { todos[todoIndex] = todo; } else { todos.add(todo); }
_todoStreamController.add(todos);
}
Broadcast
Stream<List> getTodos() => _todoStreamController.asBroadcastStream();
Subscribe
Future _onSubscriptionRequested( TodosOverviewSubscriptionRequested event, Emitter emit, ) async { emit(state.copyWith(status: () => TodosOverviewStatus.loading));
await emit.forEach<List<Todo>>(
_todosRepository.getTodos(),
onData: (todos) => state.copyWith(
status: () => TodosOverviewStatus.success,
todos: () => todos,
),
onError: (_, __) => state.copyWith(
status: () => TodosOverviewStatus.failure,
),
);
}
Upvotes: 0
Reputation: 4013
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.
Upvotes: 7
Reputation: 30312
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.
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()
).
Upvotes: 63
Reputation: 971
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();
}
Upvotes: 2