Menu
CoddyTech

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.

challenge icon

Sfida

Medio

Tocca 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 initState con fetch('/tip')
  • passa _tip a FutureBuilder

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();
              },
            ),
        ),
      ),
    );
  }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Dati e rete

Esercitati da solo: Compilatore Flutter online