Home > Back-end >  Multiple StreamBuilder that using same stream work incorrectly?
Multiple StreamBuilder that using same stream work incorrectly?

Time:07-05

Let say I have code like this

class ScreenA extends StatelessWidget {
  const ScreenA();

  @override
  Widget build(BuildContext context) {
    final Stream<List<Order>> ordersStream = Order.stream;
    return Column(
      children: [
        StreamBuilder(
          stream: ordersStream,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              return Text(snapshot.data!.toString());
            } else {
              return const LoadingCircle();
            }
          },
        ),
        TextButton(
          child: Text('to ScreenB'),
          onPressed: () => MaterialPageRoute(
            builder: (context) =>
                ScreenB(ordersStream), // pass stream to another screen
          ),
        ),
      ],
    );
  }
}

class ScreenB extends StatelessWidget {
  const ScreenB(this.ordersStream);

  final Stream<List<Order>> ordersStream;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: ordersStream,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          return Text(snapshot.data!.toString());
        } else {
          return const LoadingCircle();
        }
      },
    );
  }
}

This seem to work, but when ScreenA already got data, in ScreenB snapshot.ConnectionState will mark as ConnectionState.waiting until ordersStream emit new value (It should get data as same as ScreenA).

For example;

at second 0: created ordersStream

at second 1: ordersStream emit value [Order1,Order2]

at second 5: I press button to go to ScreenB <- ordersStream in ScreenB should get [Order1,Order2] too, but it didn't give any value and has state ConnectionState.waiting.

at second 10: ordersStream emit value [Order3,Order4] <- ordersStream in ScreenB get value now.

I tried using StreamProvider, but it doesn't fit my code project, how to make this work correctly without StreamProvider?

CodePudding user response:

Try adding the stream key inside the builders.

StreamBuilder(
          stream: ordersStream, //add stream here
          builder: (BuildContext context, snapshot) {
           return Container();            
        }
 )

Edit

You can pass the current data along with the stream and in the second screen you can set the initial data with the data that you recieved from screen 1

StreamBuilder(
 initialData: YourCurrentDataFromScreen1,
 stream: streamHere,
 builder: (BuildContext context, snapshot) {
           return Container();            
        }
}

CodePudding user response:

This is how broadcast stream works.

You can start listening to such a stream at any time, and you get the events that are fired while you listen.

See Broadcast streams.

  • Related