Jonas
Jonas

Reputation: 7875

Can a Stream be listened to once at a time or once in general?

I have this StreamController:

StreamController<Workout> _selectedWorkoutSubject = new StreamController()

I listen to it in a StreamBuilder like this:

StreamBuilder(
  stream: workoutBloc.selectedWorkoutStream,
  builder: (BuildContext context, AsyncSnapshot<Workout> snapshot) {
    if (snapshot.hasData) {
      return ...
    } else {
      return Text('loading...');
    }
  }
);

When I leave the current page and return to it, I get the Exception: Bad state: Stream has already been listened to. I know I can only once at a time but isn't that what I'm doing? When I leave the page, the StreamBuilder should get Garbage collected which frees the stream, so something else could listen to it.

Or can a Stream only be listend to once in general (Not once at a time)? I know I can just do

StreamController<Workout> _selectedWorkoutSubject = new StreamController.broadcast();

But I'm trying to understand why it doesn't work the way I originally did it.

Upvotes: 1

Views: 1867

Answers (2)

lrn
lrn

Reputation: 71623

It's not "one at a time". A traditional non-broadcast stream can only be listened to once, ever. It only allows one listener, and when that listener cancels, the stream cleans up after itself and won't work again.

A traditional broadcast stream can be listened to many times, but all concurrent listeners get the same events.

Most Stream constructors and StreamControllers create either traditional "single-subscription" streams or broadcast streams.

There has been added another way to create a stream which can be listened to more than once: The Stream.multi constructor. With that, you can treat each listen call individually, and send whichever events you want to them, not necessarily the same values all listeners (each listen call gets its own indivudual StreamController).

You can implement the behavior of a broadcast stream using that, but you don't have to.

Other than that, using a broadcast stream is your best choice. The broadcast stream controller does get onCancel and onListen events when it stops having listeners and starts having listeners again, so you can avoid doing work when there are no listeners. With Stream.multi, you have to keep record of all the listeners yourself.

Upvotes: 3

Fellipe Malta
Fellipe Malta

Reputation: 3510

Try a few things:

  1. Set the initial data of the stream builder
  2. Change the StreamController to a BehaviorSubject (RxDart lib)

I think the first tip will help you out,

Upvotes: 1

Related Questions