Caricare una sola volta in initState
Fa parte della sezione Dati e rete del percorso Flutter di Coddy. Lezione 7 di 27.
Flutter richiama build ogni volta che la schermata si ridisegna: dopo ogni setState, quando ruoti il telefono, quando cambia un widget genitore. Può accadere molte volte al secondo. build dovrebbe solo descrivere la schermata, mai avviare operazioni.
Quindi, un fetch scritto dentro build viene eseguito di nuovo a ogni ridisegno. Ogni esecuzione è una nuova richiesta al server e la schermata può passare a una risposta diversa senza che nessuno l'abbia richiesta:
// una nuova richiesta a ogni ridisegno
FutureBuilder<String>(
future: fetch('/tip'),
...
)Crea il future una sola volta, quando si apre la schermata, in initState, e passa ogni volta lo stesso future a FutureBuilder:
late Future<String> _tip;
@override
void initState() {
super.initState();
_tip = fetch('/tip');
}initState viene eseguito una volta, prima del primo build. Avvialo con super.initState();, come richiede Flutter.
Sfida
MedioTocca il cuore nella barra superiore: il suggerimento cambia, perché fetch è in build. Carica il suggerimento una sola volta:
- aggiungi
late Future<String> _tip;allo stato - impostalo in
initStateconfetch('/tip') - passa
_tipaFutureBuilder
Provalo tu
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();
},
),
),
),
);
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Dati e rete
2Schermate di caricamento
Un indicatore durante il caricamentoConosci FutureBuilderCaricare una sola volta in initStateRicaricare i dati con un pulsanteScorri per aggiornareEsercitati da solo: Compilatore Flutter online