4

I have a streamBuilder inside a stateful widget that gets data asynchronously from the server. Additionally, I have a list that collects those data.

StreamBuilder(   
  stream: myStream.stream,   
  initialData: initData,   
  builder: (BuildContext context, AsyncSnapshot snapshot) {
        switch(snapshot.connectionState){
          case (Connection.active):
            setState(() { 
              data = data + snapshot.data;
            });
            break;
          default: 
            break;
        }   
      } 
)

If I do this, I get the setState() or markNeedBuild() was called during build.

How do I solve this problem?

MoneyBall
  • 2,343
  • 5
  • 26
  • 59
  • use for example `Stream.map()` method to concatenate stream data – pskink Oct 02 '20 at 13:46
  • @pskink isn't `stream.map()` for transforming incoming data? I'm trying to collect data. – MoneyBall Oct 02 '20 at 13:47
  • @pskink I'm confused to what you mean by return the original `event` – MoneyBall Oct 02 '20 at 13:48
  • stream.map((event) {foo += event; return event;}) – pskink Oct 02 '20 at 13:49
  • @pskink hmm I think I get what you are saying, but isn't that a bit hacky? What's the best practice with this kind of tasks? – MoneyBall Oct 02 '20 at 13:52
  • `Stream.transform` maybe? but i dont think it pays off in your case... – pskink Oct 02 '20 at 13:56
  • @pskink I guess I can forgo the streambuilder and use stream.listen on events instead. – MoneyBall Oct 02 '20 at 14:03
  • 1
    btw check https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html, it reads: *"Widget rebuilding is scheduled by each interaction, using State.setState, but is otherwise decoupled from the timing of the stream. The builder is called at the discretion of the Flutter pipeline, and will thus receive a timing-dependent sub-sequence of the snapshots that represent the interaction with the stream."* – pskink Oct 02 '20 at 14:04
  • @pskink setState inside stream listen doesn't trigger widget rebuild. So I guess I'll have to post a new question on that. – MoneyBall Oct 02 '20 at 14:12
  • @pskink I got rid of `StreamBuilder` and used `stream.listen((event) {setState((){ data = data + event; }); }`, and I initialized it in `initState()` of my stateful Widget – MoneyBall Oct 02 '20 at 14:15
  • @pskink that was my mistake. it works. Thank you for all the suggestions! – MoneyBall Oct 02 '20 at 14:20

1 Answers1

1

Flutter StreamBuilder doesn't need to call setState to rebuild its children. StreamBuilder rebuilds by default when change were detected on stream. If no Widgets are needed to be rebuilt inside the StreamBuilder, you may consider initializing a Stream listener and append the new data when changes were detected on stream.

Omatt
  • 8,564
  • 2
  • 42
  • 144