Menu
CoddyTech

Fetch Once in initState

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

Flutter calls build again every time the screen redraws: after each setState, when the phone turns, when a parent changes. That can be many times a second. build should only describe the screen, never start work.

So a fetch written inside build runs again on every redraw. Each run is a new request to the server, and the screen can jump to a different answer when nothing asked for one:

// a new request on every redraw
FutureBuilder<String>(
  future: fetch('/tip'),
  ...
)

Make the future once, when the screen opens, in initState, and give FutureBuilder that same future each time:

late Future<String> _tip;

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

initState runs once, before the first build. Start it with super.initState();, the way Flutter asks.

challenge icon

Challenge

Medium

Tap the heart in the top bar: the tip changes, because the fetch is in build. Load the tip once:

  • add late Future<String> _tip; to the state
  • set it in initState with fetch('/tip')
  • give the FutureBuilder _tip

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> {
  bool liked = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tip of the Day'),
        actions: [
          IconButton(
            icon: Icon(liked ? Icons.favorite : Icons.favorite_border),
            onPressed: () {
              setState(() {
                liked = !liked;
              });
            },
          ),
        ],
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: FutureBuilder<String>(
              future: fetch('/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