Question #337MediumWidgets & UI

What is FutureBuilder in Flutter and how is it used to build dynamic UI?

#widget#async#futurebuilder

Answer

Overview

text
FutureBuilder
is a Flutter widget that builds itself based on the latest snapshot of a
text
Future
. It handles the three states of an async operation: loading, success, and error.


Basic Structure

dart
FutureBuilder<DataType>(
  future: myFuture,          // The Future to listen to
  builder: (context, snapshot) {
    // snapshot.connectionState — loading/done
    // snapshot.data — result when done
    // snapshot.error — error if failed
  },
)

Full Example

dart
class UserProfileScreen extends StatelessWidget {
  Future<User> fetchUser() async {
    final response = await http.get(Uri.parse('https://api.example.com/user/1'));
    return User.fromJson(jsonDecode(response.body));
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Profile')),
      body: FutureBuilder<User>(
        future: fetchUser(),
        builder: (context, snapshot) {
          // Loading state
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          }
          // Error state
          if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          }
          // Success state
          if (snapshot.hasData) {
            final user = snapshot.data!;
            return Column(
              children: [
                CircleAvatar(backgroundImage: NetworkImage(user.avatarUrl)),
                Text(user.name),
                Text(user.email),
              ],
            );
          }
          return SizedBox.shrink();
        },
      ),
    );
  }
}

ConnectionState Values

StateMeaning
text
none
No Future provided
text
waiting
Future is in progress
text
active
Only for Streams
text
done
Future is complete

Avoid Rebuilding Future on Each Build

dart
class _MyState extends State<MyWidget> {
  late Future<User> _userFuture;

  
  void initState() {
    super.initState();
    _userFuture = fetchUser(); // ✅ Store it — don't call in build()
  }

  
  Widget build(BuildContext context) {
    return FutureBuilder<User>(
      future: _userFuture, // ✅ Reuse same Future
      builder: (context, snapshot) { ... },
    );
  }
}

⚠️ Never call

text
future: fetchUser()
directly in build — it creates a new Future on each rebuild!


FutureBuilder vs StreamBuilder

FeatureFutureBuilderStreamBuilder
Data type
text
Future
(single value)
text
Stream
(multiple values)
UpdatesOnce when Future completesEvery time Stream emits
Use caseOne-time API fetchReal-time data (Firestore, WebSocket)

Best Practice: Use

text
FutureBuilder
for one-time async data loads. For real-time updates, use
text
StreamBuilder
.