Flutter StreamBuilder vs FutureBuilder
Asked Answered
E

7

152

What is the main difference between StreamBuilder and FutureBuilder.

  • What to use and when to use?

  • What are the tasks they are intended to perform?

  • How each of them listens to changes in a dynamic list?

Electrical answered 13/6, 2018 at 19:5 Comment(2)
They are pretty much the same. FutureBuilder removes some boilerplate codes look at here #51983511Opportunism
Thanks for asking this important question.Unseemly
D
223

Both StreamBuilder and FutureBuilder have the same behavior: They listen to changes on their respective object. And trigger a new build when they are notified of a new value.

So in the end, their differences are how the object they listen to works.

Future is like Promise in JS or Task in c#. They are the representation of an asynchronous request. Futures have one and only one response. A common usage of Future is to handle HTTP calls. What you can listen to on a Future is its state. Whether it's done, finished with success, or had an error. But that's it.

Stream on the other hand is like async Iterator in JS. This can be assimilated to a value that can change over time. It usually is the representation of web-sockets or events (such as clicks). By listening to a Stream you'll get each new value and also if the Stream had an error or completed.

How each of them listens to changes in a dynamic list?

A Future can't listen to a variable change. It's a one-time response. Instead, you'll need to use a Stream.

Disperse answered 13/6, 2018 at 19:31 Comment(0)
J
73

FutureBuilder is used for one time response, like taking an image from Camera, getting data once from native platform (like fetching device battery), getting file reference, making an http request etc.

On the other hand, StreamBuilder is used for fetching some data more than once, like listening for location update, playing a music, stopwatch, etc.


Here is full example mentioning both cases.

FutureBuilder solves a square value and returns the result after 5 seconds, till then we show progress indicator to the user.

StreamBuilder shows a stopwatch, incrementing _count value by 1 every second.

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _count = 0; // used by StreamBuilder

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          _buildFutureBuilder(),
          SizedBox(height: 24),
          _buildStreamBuilder(),
        ],
      ),
    );
  }

  // constructing FutureBuilder
  Widget _buildFutureBuilder() {
    return Center(
      child: FutureBuilder<int>(
        future: _calculateSquare(10),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done)
            return Text("Square = ${snapshot.data}");

          return CircularProgressIndicator();
        },
      ),
    );
  }

  // used by FutureBuilder
  Future<int> _calculateSquare(int num) async {
    await Future.delayed(Duration(seconds: 5));
    return num * num;
  }

  // constructing StreamBuilder
  Widget _buildStreamBuilder() {
    return Center(
      child: StreamBuilder<int>(
        stream: _stopwatch(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active)
            return Text("Stopwatch = ${snapshot.data}");

          return CircularProgressIndicator();
        },
      ),
    );
  }

  // used by StreamBuilder
  Stream<int> _stopwatch() async* {
    while (true) {
      await Future.delayed(Duration(seconds: 1));
      yield _count++;
    }
  }
}
Jeopardize answered 30/5, 2019 at 12:50 Comment(2)
So, if I want to real time data update in from an API or URL/ HTTP request, which one I should use ?Timeout
StreamBuilderJeopardize
T
55

I find that sometimes real-world analogies work well for explaining / remembering concepts. Here's one - it's not perfect but it helps me.

Think that you are at one of those modern sushi restaurants where you have a belt going around the room with sushi boats on it. You just sit down and wait till one goes by, grab it and eat. But they also allow you to order carry out.

A Future is like the token with a number on it that they give you when you order takeout; you made the request, but the result is not yet ready but you have a placeholder. And when the result is ready, you get a callback (the digital board above the takeout counter shows your number or they shout it out) - you can now go in and grab your food (the result) to take out.

A Stream is like that belt carrying little sushi bowls. By sitting down at that table, you've "subscribed" to the stream. You don't know when the next sushi boat will arrive - but when the chef (message source) places it in the stream (belt), then the subscribers will receive it. The important thing to note is that they arrive asynchronously (you have no idea when the next boat/message will come) but they will arrive in sequence (i.e., if the chef puts three types of sushi on the belt, in some order -- you will see them come by you in that same order)

From a coding perspective -- both Futures and Streams help you deal with asynchrony (where things don't happen instantly, and you don't know when you will get a result after you make a request).

The difference is that Futures are about one-shot request/response (I ask, there is a delay, I get a notification that my Future is ready to collect, and I'm done!) whereas Streams are a continuous series of responses to a single request (I ask, there is a delay, then I keep getting responses until the stream dries up or I decide to close it and walk away).

Hope that helps.

Touchdown answered 6/1, 2020 at 10:55 Comment(0)
G
5

Both StreamBuilder and FutureBuilder widgets in Flutter allow you to build reactive UIs that respond to asynchronous data changes. However, they have some differences in terms of their usage and the type of data they work with.

FutureBuilder widget is used when you want to asynchronously retrieve a single piece of data that will not change over time, such as a network request for user information. It expects a Future as its data source, and when the Future completes, it rebuilds the widget tree with the resulting data.

StreamBuilder widget, on the other hand, is used when you want to display data that can change over time, such as a real-time chat application. It expects a Stream as its data source, and whenever new data is available, it rebuilds the widget tree with the updated data.

Here are some other differences:

FutureBuilder has a single AsyncSnapshot that represents the current state of the Future, while StreamBuilder has multiple AsyncSnapshots, each representing a new piece of data emitted by the Stream. FutureBuilder will execute the Future every time the widget is rebuilt, while StreamBuilder will only subscribe to the Stream once when the widget is mounted, and unsubscribe when the widget is disposed. Here's an example of using FutureBuilder:

FutureBuilder<String>(
  future: fetchData(),
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      return Text(snapshot.data);
    } else {
      return CircularProgressIndicator();
    }
  },
);

And here's an example of using StreamBuilder:

StreamBuilder<int>(
  stream: countStream(),
  builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
    if (snapshot.hasData) {
      return Text('Count: ${snapshot.data}');
    } else {
      return CircularProgressIndicator();
    }
  },
);

In summary, FutureBuilder is used for one-time asynchronous data retrieval, while StreamBuilder is used for displaying continuously updating data.

Gasaway answered 22/2, 2023 at 19:22 Comment(0)
E
2

StreamBuilder and FutureBuilder are both widgets that can be used to listen to asynchronous data changes in Flutter. StreamBuilder is used for displaying data that is continuously updating, while FutureBuilder is used for displaying data that is retrieved once.

StreamBuilder listens to changes in a stream of data, while FutureBuilder listens to the state of a Future. This means that StreamBuilder can be used to display data that is constantly changing, such as a live stock ticker, while FutureBuilder can only be used to display data that is retrieved once, such as the results of a network request.

StreamBuilder is more complex to set up than FutureBuilder, but it is more flexible and can be used to display more complex data.

In general, you should use StreamBuilder when you need to display data that is continuously updating, and FutureBuilder when you need to display data that is retrieved once.

Enki answered 30/6, 2023 at 11:58 Comment(0)
B
1

FutureBuilder and StreamBuilder behave similarly: they listen for changes in their respective objects. In response to changing value notifications, a new build is triggered.

Ultimately, the difference lies in how they listen to async calls.

FutureBuilder

There is only one response to it. Futures are commonly used in http calls. The Future can be used to listen to the state, e.g., when it has completed fetching the data or had an error.

like as example link here.

StreamBuilder

As opposed to streams, which are iterators that can assimilate different values, which will change over time. Each new value is returned by Stream along with an error message or success message if it has any.

like as example link here.

Conclusion

The following data might help you understand the above better:

If your use case is to just get the data, and display it, like Total number of courses from a class from API. Then you can use FutureBuilder. What if, the data updates every second or minute, while you use the app, like upcoming posts in a blog or increase comments on the blog or increase in likes on the blog. It updates asynchronously at certain interval, in that case StreamBuilder is the best option. Bases upon the use case, you decide which one to use. Both of them are good in their own way.

Berny answered 15/8, 2022 at 14:43 Comment(0)
E
0

Here is a full example mentioning both cases. FutureBuilder solves a square value and returns the result after 5 seconds, till then we show a progress indicator to the user.

StreamBuilder shows a stopwatch, incrementing _count value by 1 every second.

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _count = 0; // used by StreamBuilder

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          _buildFutureBuilder(),
          SizedBox(height: 24),
          _buildStreamBuilder(),
        ],
      ),
    );
  }

  // constructing FutureBuilder
  Widget _buildFutureBuilder() {
    return Center(
      child: FutureBuilder<int>(
        future: _calculateSquare(10),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done)
            return Text("Square = ${snapshot.data}");

          return CircularProgressIndicator();
        },
      ),
    );
  }

  // used by FutureBuilder
  Future<int> _calculateSquare(int num) async {
    await Future.delayed(Duration(seconds: 5));
    return num * num;
  }

  // constructing StreamBuilder
  Widget _buildStreamBuilder() {
    return Center(
      child: StreamBuilder<int>(
        stream: _stopwatch(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active)
            return Text("Stopwatch = ${snapshot.data}");

          return CircularProgressIndicator();
        },
      ),
    );
  }

  // used by StreamBuilder
  Stream<int> _stopwatch() async* {
    while (true) {
      await Future.delayed(Duration(seconds: 1));
      yield _count++;
    }
  }
}
Eblis answered 3/10, 2022 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.