Pour diverses raisons, la build
méthode de mes widgets est parfois appelée à nouveau.
Je sais que cela arrive parce qu'un parent a mis à jour. Mais cela provoque des effets indésirables. Une situation typique où cela pose des problèmes est lors de l'utilisation de FutureBuilder
cette façon:
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: httpCall(),
builder: (context, snapshot) {
// create some layout here
},
);
}
Dans cet exemple, si la méthode de construction devait être appelée à nouveau, elle déclencherait une autre requête http. Ce qui est indésirable.
Compte tenu de cela, comment gérer la construction indésirable? Y a-t-il un moyen d'empêcher l'appel de construction?
flutter
flutter-widget
Rémi Rousselet
la source
la source
Réponses:
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:
Class.of(context)
changement (de modèle)Cela signifie que la
build
mé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
StatefulWidget
puis extrairiez cet appel HTTP vers leinitState
de votreState
: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
const
constructeurs de fléchettes :Grâce à ce
const
mot - clé, l'instance deDecoratedBox
restera la même même si build a été appelé des centaines de fois.Mais vous pouvez obtenir le même résultat manuellement:
Dans cet exemple, lorsque StreamBuilder est notifié des nouvelles valeurs,
subtree
il ne sera pas reconstruit même si StreamBuilder / Column le fait. Cela arrive parce que, grâce à la fermeture, l'instance deMyWidget
n'a pas changé.Ce modèle est beaucoup utilisé dans les animations. Les utilisations typiques sont
AnimatedBuilder
et toutes les transitions telles queAlignTransition
.Vous pouvez également stocker
subtree
dans un champ de votre classe, bien que moins recommandé car cela interrompt la fonction de rechargement à chaud.la source
subtree
dans un champ de classe interrompt le rechargement à chaud?StreamBuilder
est que lorsque le clavier apparaît, l'écran change, donc les routes doivent être reconstruites. AinsiStreamBuilder
est reconstruit et un nouveauStreamBuilder
est créé et il s'abonne austream
. Quand unStreamBuilder
s'abonne à unstream
,snapshot.connectionState
devientConnectionState.waiting
ce qui fait que mon code renvoie unCircularProgressIndicator
, puissnapshot.connectionState
change lorsqu'il y a des données, et mon code renverra un widget différent, ce qui fait scintiller l'écran avec des éléments différents.StatefulWidget
, de m'abonner austream
oninitState()
et de définir lecurrentWidget
avecsetState()
commestream
envoie de nouvelles données, en passantcurrentWidget
à labuild()
méthode. Y a-t-il une meilleure solution?FutureBuilder
.Vous pouvez empêcher les appels de build indésirables, en utilisant ces méthodes
1) Créer une classe Statefull enfant pour une petite partie individuelle de l'interface utilisateur
2) Utilisez la bibliothèque Provider , donc en l'utilisant, vous pouvez arrêter l'appel de méthode de construction indésirable
Dans ces situations ci-dessous, appel de méthode de construction
la source
Flutter a également
ValueListenableBuilder<T> class
. Il vous permet de reconstruire uniquement certains des widgets nécessaires à votre objectif et de sauter les widgets coûteux.vous pouvez voir les documents ici ValueListenableBuilder flutter docs
ou juste l'exemple de code ci-dessous:
la source