La méthode de construction est conçue de manière à être pure / sans effets secondaires . En effet, de nombreux facteurs externes peuvent déclencher une nouvelle construction de widget, tels que:
- Route pop / push
- Redimensionnement de l'écran, généralement en raison de l'apparence du clavier ou du changement d'orientation
- Le widget parent a recréé son enfant
- Un InheritedWidget dont le widget dépend du
Class.of(context)changement (de modèle)
Cela signifie que la buildméthode ne doit pas déclencher un appel http ni modifier aucun état .
Comment cela est-il lié à la question?
Le problème auquel vous êtes confronté est que votre méthode de build a des effets secondaires / n'est pas pure, ce qui rend les appels de build superflus gênants.
Au lieu d'empêcher l'appel de build, vous devez rendre votre méthode de build pure, afin qu'elle puisse être appelée à tout moment sans impact.
Dans le cas de votre exemple, vous transformeriez votre widget en un StatefulWidgetpuis extrairiez cet appel HTTP vers le initStatede votre State:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<int> future;
@override
void initState() {
future = Future.value(42);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// create some layout here
},
);
}
}
Je le sais déjà. Je suis venu ici parce que je veux vraiment optimiser les reconstructions
Il est également possible de créer un widget capable de se reconstruire sans forcer ses enfants à construire aussi.
Lorsque l'instance d'un widget reste la même; Flutter ne reconstruira pas volontairement les enfants. Cela implique que vous pouvez mettre en cache des parties de votre arborescence de widgets pour éviter les reconstructions inutiles.
Le moyen le plus simple consiste à utiliser des constconstructeurs de fléchettes :
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
Grâce à ce constmot - clé, l'instance de DecoratedBoxrestera la même même si build a été appelé des centaines de fois.
Mais vous pouvez obtenir le même résultat manuellement:
@override
Widget build(BuildContext context) {
final subtree = MyWidget(
child: Text("Hello World")
);
return StreamBuilder<String>(
stream: stream,
initialData: "Foo",
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text(snapshot.data),
subtree,
],
);
},
);
}
Dans cet exemple, lorsque StreamBuilder est notifié des nouvelles valeurs, subtreeil ne sera pas reconstruit même si StreamBuilder / Column le fait. Cela arrive parce que, grâce à la fermeture, l'instance de MyWidgetn'a pas changé.
Ce modèle est beaucoup utilisé dans les animations. Les utilisations typiques sont AnimatedBuilderet toutes les transitions telles que AlignTransition.
Vous pouvez également stocker subtreedans un champ de votre classe, bien que moins recommandé car cela interrompt la fonction de rechargement à chaud.