Adelina
Adelina

Reputation: 11881

Should I cancel StreamSubscription after closing Stream?

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

Answers (4)

Code Spirit
Code Spirit

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

Dr Younss AIT MOU
Dr Younss AIT MOU

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

Ravi Sevta
Ravi Sevta

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

Riwen
Riwen

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

Related Questions