Search code examples
flutterdartstream-builder

Flutter: 'Stream has already been listened to.'


I have a DefaultTabController with two tabs which work fine. On my second tab I have recently added a stream controller to update a value on screen everytime that value changes which also works fine, but if I was to swift left to the first tab then back to the second I get the following error.

Stream has already been listened to.

I have a dispose function but due to not navigating to another page it does not trigger so it create many stream, which I don't want it to do.

All the code below is for the stream controller, if I comment all this code out, the app works fine without the error and ive also found out if I comment out only stream: stream_controller.stream, I also dont get the error.

StreamController<int> stream_controller = StreamController<int>();
@override
  void dispose(){
    super.dispose();
    stream_controller.close();
   
  } 
StreamBuilder(
                                          initialData: 0,
                                          stream: stream_controller.stream,
                                          builder: (context, snapshot) {
                                            return Padding(
                                              padding: const EdgeInsets.all(8.0),
                                              child: Text(
                                                '#${snapshot.data}',
                                              ),
                                            );
                                          })
 stream_controller.sink.add(rank);

Solution

  • Stream<T>s can only be listened once. To enable any number of listeners, use:

    StreamController<int> stream_controller = StreamController<int>.broadcast();
    

    Also in your context seems you're reusing the same StreamController instance. Try defining it inside initState rather of as class field:

    class _MyState extends State<T> {
      late StreamController<int> stream_controller;
    
      @override
      void initState() {
        super.initState();
        stream_controller = StreamController<int>.broadcast();
      }
    
      @override
      void dispose(){
        stream_controller.close();
        super.dispose();
      } 
    }
    

    A broadcast stream allows any number of listeners, and it fires its events when they are ready, whether there are listeners or not.

    See complete Stream documentation for details.