How to use FlutterBuilder properly and common mistakes!

One of the biggest mistakes that I see people make while reading Stack Overflow and looking through different tutorials is using FlutterBuilder the inefficient way. I’m writing this article to emphasize the correct usage of FlutterBuilder and show one of the biggest mistakes that I see people make.

The most common problem!

Here is a pice a code that has a major flow, can you spot the problem?

// getData - async network request to fetch data
@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<List<String>>(
          future: getData(),
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasError) {
              return Center(
                child: Text("Error"),
              );
            } else if (snapshot.hasData) {
              return PersonUI(snapshop.data);
            } else {
              return Center(
                child: Container(),
              );
            }
          },
        ),
      ),
    );
  }

If the answer is no, then you are not alone. I’ve seen many people doing this mistake and I also did it while learning Flutter.

  • You should never create your Future where you define your FutureBuilder!

The code above on Line 6 calls getData() to pass in a future to the FutureBuilder widget. The problem is that we are essentially creating a new instance of the Future returned by the method getData() every time the widget builds. A widget can be rebuild MANY times during the lifetime of an app and you probably want to load your data only once.

At a first glance, just opening the app and rendering the UI calls the build method at least 3 times. This means that we will make 3 network requests to fetch the same data! This problem is so common, that even when the Flutter team made a video about FlutterBuilder, they forgot to mention this issue in the demo code that they presented.

How to use FlutterBuilder the right way!

We should store the Future returned by the getData() method into a local variable and use that in the FutureBuilder.

 late Future<List<String>> _dataFuture;

  @override
  void initState() {
    super.initState();
    _dataFuture = getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<List<String>>(
          future: dataFuture,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasError) {
              return Center(
                child: Text("Error"),
              );
            } else if (snapshot.hasData) {
              return PersonUI(snapshop.data);
            } else {
              return Center(
                child: Container(),
              );
            }
          },
        ),
      ),
    );
  }

This is also highlighted at the top of the FlutterBuilder documentation: “The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the Future”.

I’m hoping this was helpful and now you know how to use FlutterBuilder the right way and you will avoid this common mistake. If you would like to see other ways in which you can improve the performance of your app, checkout this post.

Also, if you found this useful, don’t forget to checkout our premium templates, maybe you can use them for your next app.

One thought on “How to use FlutterBuilder properly and common mistakes!

Leave a Reply

Your email address will not be published.