'Flutter: How to receive new Data and update Widget without rebuildung

I'm currently facing an annoying I think design problem made by myself and flutter :D

In my widgets I work with FutureBuilder. When the Widget gets created, it fetches initial the data - everything's fine. Now I got a WebSocket connection which sends me updated data. I pass this data to my widget and now I am facing the problem that either I change the data and the Widget does not reload or I additionally use setState and the widget will update itself and again fetches new data because it's rebuild and futurebuilder comes into play again. That's not efficient at all. How can I prevent this behavior.

I think about, that my Structure is maybe not right for this flutter behavior and therefore I maybe have to load the data initially outside the widget, pass em in via constructor and set a listener inside my Widget for the WebSocket notification and then call setState... right?

Here an short example that does rebuild and therefore again fetches data by itself -> so not my desired solution:

class _ExampleState extends State<Example> {

  Stream wsData;

  _ExampleState() {
    wsData.listen((event) {
      setState(() {
        //update data
      });
    });
  }

  _getData() {
    // Call network manager and fetch data
    return {'fetchedData': 'data'};
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: FutureBuilder(
          future: _getData(),
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.data != null) {
              Text('data arrived: ' + snapshot.data.toString());
            } else {
              return CircularProgressIndicator();
            }
          }),
    );
  }
}


Solution 1:[1]

My solution: In my use case it just wouldn't work with Streambuilder. The data that were passed into the Widget after new data came from the stream were the same somehow.. Now I am using FutureBuilder to fetch the data initial and pass a Stream to my Widget. The Widget listens to changes on the Stream and updates itself..

Also, like mentioned from @Rémi Rousselet, I start the fetch process in the initState method and assign it to a local future variable, instead of triggering the fetch directly with FutureBuilder.

Solution 2:[2]

If you have a data source which constantly updates itself, you can use a StreamBuilder instead of FutureBuilder. StreamBuilder listens to the data source and rebuilds the widget after every update it gets from it.

Solution 3:[3]

Recently I also faced this problem, where I was passing data from another class with setState. The data was updated initially using initState then I was changing that particular data using a local variable, but when new data arrived from the parent class this was not updating.

later I found didUpdateWidget method

@override
  void didUpdateWidget(covariant ExampleClass oldWidget) {
    print("didUpdateWidget: ${widget.value}");
    selectedIndex = widget.value.toInt().toString(); //local variable
    list.clear(); // list with data
    _buildList(); // list will rebuild with new data
    super.didUpdateWidget(oldWidget);
  }

basically using this override method in the stateful class we can do something whenever there is a change in the widget.
Now I can update the data using local and parent variables.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 CAoT
Solution 2 Cankat Örüm
Solution 3 Sanjay Chakrapani