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
MediumTap 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
initStatewithfetch('/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();
},
),
),
),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
2Loading Screens
A Spinner While LoadingMeet FutureBuilderFetch Once in initStateReload Data With a ButtonPull to RefreshPractice on your own: Online Flutter compiler