Busque uma vez no initState
Parte da seção Dados e rede do Journey de Flutter da Coddy. Lição 7 de 27.
O Flutter chama build novamente sempre que a tela é redesenhada: após cada setState, quando o celular é girado, quando um widget pai muda. Isso pode acontecer muitas vezes por segundo. build deve apenas descrever a tela, nunca iniciar tarefas.
Por isso, um fetch escrito dentro de build é executado novamente a cada redesenho. Cada execução é uma nova solicitação ao servidor, e a tela pode mudar para uma resposta diferente sem que ninguém tenha pedido:
// uma nova requisição a cada redesenho
FutureBuilder<String>(
future: fetch('/tip'),
...
)Crie o future uma única vez, quando a tela abrir, em initState, e passe esse mesmo future para FutureBuilder todas as vezes:
late Future<String> _tip;
@override
void initState() {
super.initState();
_tip = fetch('/tip');
}initState é executado uma vez, antes do primeiro build. Inicie-o com super.initState();, como o Flutter exige.
Desafio
MédioToque no coração na barra superior: a dica muda, porque o fetch está em build. Carregue a dica uma vez:
- adicione
late Future<String> _tip;ao estado - defina-o em
initStatecomfetch('/tip') - passe
_tippara oFutureBuilder
Experimente você mesmo
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();
},
),
),
),
);
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Dados e rede
2Telas de carregamento
Um indicador giratório durante o carregamentoConheça o FutureBuilderBusque uma vez no initStateRecarregue os dados com um botãoPuxe para atualizarPratique por conta própria: Compilador de Flutter online