Open In App

Flutter – FutureBuilder Widget

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

In Flutter, the FutureBuilder Widget is used to create widgets based on the latest snapshot of interaction with a Future.  It is necessary for Future to be obtained earlier either through a change of state or change in dependencies. FutureBuilder is a Widget that will help you to execute some asynchronous function and based on that function’s result your UI will update.

FutureBuilder is Stateful by nature i.e it maintains its own state as we do in StatefulWidgets.

Syntax:

FutureBuilder(
  Key key,
  this.future,
  this.initialData,
  @required this.builder,
)
And, builder should not be null.

When we use the FutureBuilder widget we need to check for future state i.e future is resolved or not and so on. There is various State as follows:

  1. ConnectionState.none: It means that the future is null and initialData is used as defaultValue.
  2. ConnectionState.active: It means the future is not null but it is not resolved yet.
  3. ConnectionState.waiting: It means the future is being resolved, and we will get the result soon enough.
  4. ConnectionState.done: It means that the future has been resolved.

We will create FutureBuilder Widget in a step by step manner.

Step 1: Create a future that needs to be resolved.

Dart




/// Function that will return a
/// "string" after some time
/// To demonstrate network call
/// delay of [2 seconds] is used
///
/// This function will behave as an
/// asynchronous function
Future<String> getData() {
  return Future.delayed(Duration(seconds: 2), () {
    return "I am data";
    // throw Exception("Custom Error");
  });
}


The above snippet is to demonstrate a real network call. We have used a 2 seconds delay.

Step 2: Create a FutureBuilder Widget and manage the waiting state.

Dart




FutureBuilder(
  builder: (ctx, snapshot) {
    ... some code here
       
    // Displaying LoadingSpinner to indicate waiting state
    return Center(
      child: CircularProgressIndicator(),
    );
  },
   
  // Future that needs to be resolved
  // inorder to display something on the Canvas
  future: getData(),
),


In this snippet, we can see we are returning a LoadingSpinner. It will only be displayed when the future is in the Waiting state.

Step 3: Manage Future done state i.e when the future is resolved. This step also requires checking for any error that could occur during a network call.

Dart




FutureBuilder(
  builder: (ctx, snapshot) {
    // Checking if future is resolved
    if (snapshot.connectionState == ConnectionState.done) {
      // If we got an error
      if (snapshot.hasError) {
        return Center(
          child: Text(
            '${snapshot.error} occurred',
            style: TextStyle(fontSize: 18),
          ),
        );
         
        // if we got our data
      } else if (snapshot.hasData) {
        // Extracting data from snapshot object
        final data = snapshot.data as String;
        return Center(
          child: Text(
            '$data',
            style: TextStyle(fontSize: 18),
          ),
        );
      }
    }
     
    ... some code here
      ),


In the above snippet, you can see we are checking

snapshot.hasError
This step is require because it could be possible that future is resolved but an error has occurred.

We are also checking

snapshot.hasData
This step is required because it may be possible that future is resolved but nothing is returned
due to some reasons, so always perform these checks otherwise you may get unexpected behaviour.

Complete Source Code: 
 

Dart




import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GeeksforGeeks',
 
      // to hide debug banner
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: HomePage(),
    );
  }
}
 
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('GeeksforGeeks'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (ctx) => FutureDemoPage(),
              ),
            ),
            child: Text('Demonstrate FutureBuilder'),
          ),
        ),
      ),
    );
  }
}
 
class FutureDemoPage extends StatelessWidget {
  /// Function that will return a
  /// "string" after some time
  /// To demonstrate network call
  /// delay of [2 seconds] is used
  ///
  /// This function will behave as an
  /// asynchronous function
  Future<String> getData() {
    return Future.delayed(Duration(seconds: 2), () {
      return "I am data";
      // throw Exception("Custom Error");
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Future Demo Page'),
        ),
        body: FutureBuilder(
          builder: (ctx, snapshot) {
            // Checking if future is resolved or not
            if (snapshot.connectionState == ConnectionState.done) {
              // If we got an error
              if (snapshot.hasError) {
                return Center(
                  child: Text(
                    '${snapshot.error} occurred',
                    style: TextStyle(fontSize: 18),
                  ),
                );
 
                // if we got our data
              } else if (snapshot.hasData) {
                // Extracting data from snapshot object
                final data = snapshot.data as String;
                return Center(
                  child: Text(
                    '$data',
                    style: TextStyle(fontSize: 18),
                  ),
                );
              }
            }
 
            // Displaying LoadingSpinner to indicate waiting state
            return Center(
              child: CircularProgressIndicator(),
            );
          },
 
          // Future that needs to be resolved
          // inorder to display something on the Canvas
          future: getData(),
        ),
      ),
    );
  }
}


Output:



Last Updated : 07 Jun, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads