Menu
CoddyTech

Meet FutureBuilder

Part of the Data and the Network section of Coddy's Flutter journey. Lesson 6 of 27.

Most screens load their data the moment they open, with no button. Flutter has a widget for showing a future: FutureBuilder. You give it the future, and it builds the screen again each time the future changes state.

FutureBuilder<String>(
  future: _message,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data!);
    }
    return const CircularProgressIndicator();
  },
)

The snapshot is what the future looks like right now. Before the answer arrives, snapshot.hasData is false, so the spinner shows. When it arrives, the builder runs again and snapshot.data holds the string.

snapshot.data has the type String?: a string or null, because there is no data at first. The ! after it says "I checked, it is not null". Use it only after hasData: on a null it crashes the app.

The starter already makes the future once, in initState, which runs when the screen opens. late tells Dart the variable gets its value there, before it is used. The next lesson shows why it lives there.

challenge icon

Challenge

Medium

The app loads the message in initState but never shows it. Replace the placeholder Text with a FutureBuilder<String> for _message:

  • a CircularProgressIndicator while it loads
  • the message, size 24, when it arrives

Try it yourself

import 'package:flutter/material.dart';

import 'api.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MessageScreen(),
    );
  }
}

class MessageScreen extends StatefulWidget {
  const MessageScreen({super.key});

  @override
  State<MessageScreen> createState() => _MessageScreenState();
}

class _MessageScreenState extends State<MessageScreen> {
  late Future<String> _message;

  @override
  void initState() {
    super.initState();
    _message = fetch('/message');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: const Text('The message goes here', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Data and the Network

Practice on your own: Online Flutter compiler