Menu
CoddyTech

Reload Data With a Button

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

To load fresh data, give the FutureBuilder a new future. Make it in setState, so the screen rebuilds with it:

IconButton(
  icon: const Icon(Icons.refresh),
  onPressed: () {
    setState(() {
      _tip = fetch('/tip');
    });
  },
)

The new tip arrives 2 seconds later. While it loads, snapshot.hasData stays true: the builder keeps the old data until new data replaces it. With a hasData check, the old tip stays on the screen and nothing shows that the app is working.

To show the spinner again, ask snapshot.connectionState, where the future is right now. It is ConnectionState.waiting while a future runs and ConnectionState.done when it has finished:

if (snapshot.connectionState == ConnectionState.waiting) {
  return const CircularProgressIndicator();
}
return Text(snapshot.data!);

Once it is done, the data is there, so snapshot.data! is safe.

challenge icon

Challenge

Medium

Add a refresh button that loads the next tip:

  • an IconButton with Icons.refresh in the top bar's actions
  • pressing it sets _tip to a new fetch('/tip') in setState
  • the spinner shows while the new tip loads: check snapshot.connectionState

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: TipScreen(),
    );
  }
}

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

  @override
  State<TipScreen> createState() => _TipScreenState();
}

class _TipScreenState extends State<TipScreen> {
  late Future<String> _tip;

  @override
  void initState() {
    super.initState();
    _tip = fetch('/tip');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tip of the Day'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: FutureBuilder<String>(
              future: _tip,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return Text(
                    snapshot.data!,
                    textAlign: TextAlign.center,
                    style: const TextStyle(fontSize: 24),
                  );
                }
                return const CircularProgressIndicator();
              },
            ),
        ),
      ),
    );
  }
}
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