Reputation: 11881
After closing streamSink, do I still need to cancel listeners?
Found this answer: Dart: Do I have to cancel Stream subscriptions and close StreamSinks?
In general, when you are done listening to that Stream, for any reason, you should close the subscription
So if I don't cancel subscription - they would be kept open forever? Garbage collector would not deal with them?
StreamController<int> controller = StreamController<int>();
Stream stream = controller.stream;
StreamSubscription subscription = stream.listen((value) {
print('Value from controller: $value');
})
..onDone(() => print('done'));
// prints : Value from controller: 1
controller.add(1);
// prints : done
controller.close();
// still listening to closed stream
// no error - cancels successfully
Future.delayed(Duration(seconds: 2), () => subscription.cancel());
Upvotes: 1
Views: 3511
Reputation: 5041
Ive tested it today and it is not required to cancel()
a StreamSubscription
when the controller is closed because controller will emit done
when closed and remove all listeners.
Example:
import "dart:async";
void main() {
final _controller = StreamController();
final _listener = _controller.stream.listen((e) => print("Listener $e"), onDone: () => print("onDone"));
_controller.add(1);
_controller.add(2);
_controller.add(3);
_controller.close().then((_) {
print("hasListener ${_controller.hasListener}");
});
}
Output:
Listener 1
Listener 2
Listener 3
onDone
hasListener false
Upvotes: 5
Reputation: 1117
A straight forward answer: If you close your stream, cancel subscriptions. Otherwise, listeners will keep listening to a stream that will never happen ;)
Upvotes: 1
Reputation: 3075
So closing steam means you will not be able to add further events,
And if you do this:
controller.close();
controller.add(1);
it will throw the error Bad state: Cannot add event after closing
And canceling a subscription means from now onward you don't want to listen to incoming events from the stream.
In your example, if you add an event to steam after 2 seconds. it will not listen.
Future.delayed(Duration(seconds: 7), () {
controller.add(1);
controller.close();
});
what docs say:
/// Closes the stream.
///
/// No further events can be added to a closed stream.
///
/// The returned future is the same future provided by [done].
/// It is completed when the stream listeners is done sending events,
/// This happens either when the done event has been sent,
/// or when the subscriber on a single-subscription stream is canceled.
Future close();
Upvotes: 1
Reputation: 5190
According to the docs:
When the "done" event is fired, subscribers are unsubscribed before receiving the event. After the event has been sent, the stream has no subscribers. Adding new subscribers to a broadcast stream after this point is allowed, but they will just receive a new "done" event as soon as possible.
Upvotes: 2