How to solve: Force StreamBuilder to reload when switching tab

Question

Asked by kuro on November 28, 2021 (source).

Im new to the flutter SDK, I created a flutter application with two tabs.

On the first tab I have a ListView that displays items from a FutureBuilder which gets data over http.

On the second tab I have a ListView that displays items from a StreamBuilder also gets data over http after adding items to database from the 1st tab.

The problem is: when I switch tab back and forth, the 2nd tab doesnt reloads http call and show error

Bad State: Stream has already been listened to.

Unless i manually push the refresh button( which is an setState(() {}); ) then it would load again, is there a way that i can make it reload on tab change?

Here is my http call:


Future<List> getDataDB() async {
    final rep = await http.get(Uri.parse("http://192.168.0.105/fluttertest/public/showfood"));
    if (rep.statusCode == 200) {
      return jsonDecode(rep.body);
    } else {
      throw Exception('Failed to load');
    }
  }

  Future<List> getDataOrder() async {
    String id = widget.list[widget.index]['id'].toString();
    final getb = await http.get(Uri.parse("http://192.168.0.105/fluttertest/public/getbill/"+id));
    if (getb.statusCode == 200) {
      return jsonDecode(getb.body);
    } else {
      throw Exception('Failed to load');
    }
  }

Here is my StreamBuilder:

child: StreamBuilder<List>(
                    stream: Stream.periodic(Duration(seconds: 1))
                    .asyncMap((i) => getDataOrder()),
                    builder: (context,snapshot){
                      List<Widget> children;
                      if(snapshot.hasData){
                        children = <Widget>[
                          Expanded(child: BillItems(list:snapshot.data!,tableid:widget.list[widget.index]['id'])),
                        ];
                      }
                      else if (snapshot.hasError) {
                        children = <Widget>[
                          Text('Error: ${snapshot.error}'),
                        ];
                      }
                      else {
                        children = const <Widget>[
                          SizedBox(
                            child: CircularProgressIndicator(),
                          ),
                        ];
                      }
                      return Center(
                        child: Column(
                          children: children,
                        ),
                      );
                    }
                ),
'''

Answer

Question answered by mmcdon20 (source).

The problem is: when I switch tab back and forth, the 2nd tab doesnt reloads http call and show error

Bad State: Stream has already been listened to.

You haven't included the part that includes the tabs, but a Stream can only be listened to once, unless it is a broadcast stream.

This program produces the same error:

void main() {
  final stream = Stream<int>.fromIterable([1,2,3,4,5]);
  stream.forEach(print);
  stream.forEach(print);
}

And you can fix it by calling .asBroadcastStream() like so:

void main() {
  final stream = Stream<int>.fromIterable([1,2,3,4,5]).asBroadcastStream();
  stream.forEach(print);
  stream.forEach(print);
}

Video Answers on YouTube

DART FLUTTER
SHARE: