155 votes

Quelle est la relation entre les widgets avec et sans état dans Flutter ?

Un widget à état est défini comme tout widget qui change d'état au cours de sa vie. Mais il est très courant qu'un StatelessWidget d'avoir un StatefulWidget comme l'un de ses enfants. N'est pas StatelessWidget devient stateful si elle a StatefulWidget comme l'un de ses enfants ?

J'ai essayé de regarder dans la documentation comme faisant partie du code de StatelessWidget mais je n'arrivais pas à comprendre comment une StatelessWidget peut avoir Statefulwidget comme ses enfants et restent toujours StatelessWidget .

Quelle est la relation et la différence entre les widgets avec et sans état dans Flutter ?

3 votes

Vous pouvez composer votre mise en page à partir de différents types de widgets, mais cela ne signifie pas que vous héritez des caractéristiques de la composition pour affecter chaque widget. Ce que je veux dire, c'est que vous pouvez avoir un conteneur sans état qui a un enfant d'un autre conteneur qui est déclaré comme StatefulWidget quelque part ailleurs, l'état du conteneur n'affectera que ce seul composant. Il s'agit donc d'avoir une composition de différents types de widgets, chacun fonctionnant comme vous le souhaitez.

3 votes

Pour compliquer encore plus les choses, il existe un troisième type de widget : InheritedWidget Ce qui peut faire StatelessWidget mettre à jour.

135voto

Rémi Rousselet Points 45139

A StatelessWidget ne sera jamais reconstruire par elle-même (mais elle peut l'être à partir d'événements extérieurs). A StatefulWidget peut. C'est la règle d'or.

MAIS tout type de widget peut être repeint à tout moment.

Apatride signifie seulement que toutes ses propriétés sont immuable et que la seule façon de les modifier est de créer une nouvelle instance de ce widget. Il ne verrouille pas, par exemple, l'arbre des widgets.

Mais tu ne devrais pas te soucier du type de tes enfants. Cela n'a aucun impact sur vous.

16 votes

(Relativement nouveau dans le domaine). Quelle est la différence entre rebuild y repaint

0 votes

Également d'après les commentaires dans le code du framework flutter, apparemment StateFulWidget sont également immuables.

4 votes

La construction d'un widget est essentiellement un appel à la méthode "build", suivi par la création/mise à jour de la renderbox correspondante ; ce qui est suivi par le processus de peinture. Qui imprimera ces renderboxes à l'écran.

96voto

Farhana Points 2977

StatefulWidget vs StatelessWidget.

enter image description here

StatelessWidget -- Un widget qui ne nécessite pas d'état mutable.

  • Un widget sans état est un widget qui décrit une partie de l'interface utilisateur en construisant une constellation d'autres widgets qui décrivent plus concrètement l'interface utilisateur. l'interface utilisateur de manière plus concrète. Le processus de construction se poursuit récursivement jusqu'à ce que la description de l'interface utilisateur soit entièrement entièrement concrète (par exemple, elle est entièrement constituée de RenderObjectWidgets, qui décrivent des RenderObjects concrets).

  • El stateless est utile lorsque la partie de l'interface utilisateur que vous décrivez ne dépend pas d'autre chose que des informations de configuration de l'objet lui-même et de l'interface utilisateur. que les informations de configuration de l'objet lui-même et le BuildContext dans lequel le widget est gonflé. Pour les compositions qui peuvent changer dynamiquement, par exemple parce qu'elles ont un état interne ou en fonction de l'état du système, envisagez d'utiliser la fonction StatefulWidget .

class GreenFrog extends StatelessWidget {
  const GreenFrog({ Key key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFF2DBD3A));
  }
}

StatefulWidget -- Un widget qui a un état mutable.

  • Les widgets à état sont utiles lorsque la partie de l'interface utilisateur que vous décrivez peut changer de façon dynamique.

Lorsque Flutter construit un StatefulWidget il crée un objet State. Cet objet est l'endroit où tous les états mutables de ce widget sont conservés.

Le concept d'État est défini par deux choses :

1) Les données utilisées par le widget peuvent changer.

2) Les données ne peuvent pas être lues de manière synchrone lorsque le widget est construit. (Tous les état doit être établi au moment où la méthode de construction est appelée).

Cycle de vie du StatefulWidget

Le cycle de vie comporte les étapes simplifiées suivantes :

  1. createState() -- Lorsque Flutter reçoit l'instruction de construire un StatefulWidget, il appelle immédiatement createState() .
  • Crée l'état mutable pour ce widget à un emplacement donné dans l'arbre.

  • Les sous-classes doivent surcharger cette méthode pour renvoyer une instance nouvellement créée de leur sous-classe State associée :

@override
_MyState createState() => _MyState();
  1. monté == true -- Tous les widgets ont un bool this.mounted propriété. Elle devient vraie lorsque le buildContext est attribué. C'est une erreur d'appeler setState lorsqu'un widget est démonté. Si cet objet State se trouve actuellement dans un arbre.
  • Après avoir créé un objet State et avant d'appeler initState le cadre de travail "monte" l'objet State en l'associant à un objet de type
    BuildContext . L'objet State reste monté jusqu'à ce que le cadre
    appelle dispose() après quoi, le cadre ne demandera plus jamais à l'utilisateur d'utiliser l'outil.
    Objet d'État à construire à nouveau.

  • C'est une erreur d'appeler setState à moins que monté soit vrai.

bool get mounted => _element != null;
  1. initState() -- C'est la première méthode appelée lorsque le widget est créé (après le constructeur de la classe, bien sûr).

initState est appelé une fois et une seule. Il doit appeler super.initState().

  • Initialiser les données qui reposent sur le BuildContext spécifique de l'instance créée du widget.

  • Initialiser les propriétés qui dépendent du "parent" de ces widgets dans l'arbre.

  • S'abonner aux flux, ChangeNotifiers ou tout autre objet qui pourrait modifier les données de ce widget.

@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}
  1. didChangeDependencies() -- Appelé lorsqu'une dépendance de cet objet State change.
  • Cette méthode est également appelée immédiatement après initState . Il est prudent d'appeler BuildContext.inheritFromWidgetOfExactType de cette méthode.

  • Les sous-classes remplacent rarement cette méthode car le framework appelle toujours la méthode build après les changements de dépendances. Certaines sous-classes surchargent cette méthode parce qu'elles ont besoin d'effectuer un travail coûteux (par exemple, le réseau réseau) lorsque leurs dépendances changent et que ce travail serait trop coûteux trop coûteux pour être effectué à chaque build.

@protected
@mustCallSuper
void didChangeDependencies() { }
  1. construire() -- Décrit la partie de l'interface utilisateur représentée par le widget.

Le cadre appelle cette méthode dans un certain nombre de situations différentes :

  • Après avoir appelé initState .
  • Après avoir appelé didUpdateWidget .
  • Après avoir reçu un appel à setState .
  • Après qu'une dépendance de cet objet d'état change (par exemple, un InheritedWidget référencé par le build précédent change).
  • Après avoir appelé la désactivation, puis réinséré l'objet State dans l'arbre à un autre endroit.
  • La structure remplace le sous-arbre situé sous ce widget par le widget renvoyé par cette méthode, soit en mettant à jour le sous-arbre existant, soit en supprimant le sous-arbre et en gonflant un nouveau sous-arbre. existant ou en supprimant le sous-arbre et en gonflant un nouveau sous-arbre, selon que le widget renvoyé par cette méthode peut ou non mettre à jour la racine (Root) du sous-arbre existant. Racine du sous-arbre existant, comme déterminé par l'appel de la méthode Widget.canUpdate .

  • En général, les implémentations renvoient une constellation de widgets nouvellement créée, configurée avec les informations du constructeur de ce widget. de ce widget, les données BuildContext et l'état interne de cet objet State.

@override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }
  1. didUpdateWidget() -- Appelé à chaque fois que la configuration du widget est modifiée.
  • Si le widget parent est reconstruit et demande que cet emplacement dans l'arborescence soit mis à jour pour afficher un nouveau widget ayant le même type d'exécution et la même clé Widget.key, le framework mettra à jour la propriété widget de cet objet State afin de faire référence au nouveau widget. widget de cet objet State pour faire référence au nouveau widget, puis appelle cette méthode avec le widget précédent comme argument.

  • Remplacez cette méthode pour réagir lorsque le widget change (par exemple, pour lancer des animations implicites).

  • Le framework appelle toujours build après avoir appelé didUpdateWidget, ce qui signifie que tout appel à setState dans didUpdateWidget est redondant.

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
  1. setState() -- Chaque fois que vous modifiez l'état interne d'un objet State, effectuez le changement dans une fonction que vous passez à la fonction setState :
  • Appel à setState notifie au cadre que l'état interne de cet objet a changé d'une manière qui pourrait avoir un impact sur l'interface utilisateur. dans ce sous-arbre, ce qui amène le framework à planifier une construction pour les objets suivants
    cet objet État.

  • Si vous changez l'état directement sans appeler setState le cadre peut ne pas programmer une construction et l'interface utilisateur de ce sous-arbre peut ne pas être mise à jour pour refléter le nouvel état.

setState(() { _myState = newValue });
  1. désactiver() -- Deactivate est appelé lorsque l'État est retiré de l'arbre, mais il peut être réinséré avant la fin du changement de trame en cours. Cette méthode existe essentiellement parce que les objets State peuvent être déplacés d'un point à un autre de l'arbre.
  • Le framework appelle cette méthode chaque fois qu'il supprime cet objet State de l'arbre. Dans certains cas, le framework réintroduira l'objet objet State dans une autre partie de l'arbre (par exemple, si le sous-arbre contenant cet objet State est greffé d'un endroit à un autre de l'arbre). à un autre). Si cela se produit, le framework s'assurera qu'il appelle la commande build pour donner à l'objet State une chance de s'adapter à son nouvel emplacement dans l'arbre. Si le framework réintègre ce sous-arbre, il le fera avant la fin de la trame d'animation. avant la fin de la trame d'animation dans laquelle le sous-arbre a été retiré de l'arbre. retiré de l'arbre. Pour cette raison, les objets State peuvent différer la libération de la plupart des ressources jusqu'à ce que le framework appelle leur méthode leur méthode dispose.

Elle est rarement utilisée.

@protected
@mustCallSuper
void deactivate() { }
  1. dispose() -- Appelé lorsque cet objet est retiré de l'arbre de façon permanente.
  • Le cadre appelle cette méthode lorsque cet objet State ne sera plus jamais construit. Après que le framework ait appelé dispose() l'objet State est considéré comme non monté et la propriété mounted est fausse. C'est une erreur d'appeler setState à ce stade. Cette étape du cycle de vie est terminal : il n'y a aucun moyen de remonter un objet State qui a été éliminé. éliminé.

  • Les sous-classes doivent surcharger cette méthode pour libérer toutes les ressources retenues par cet objet (par exemple, arrêter toute animation active).

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}

enter image description here

Pour plus d'informations, voir aquí aquí , aquí

32voto

Saeed Jassani Points 496

D'après la documentation à l'adresse flutter.io :

...La chose importante à noter ici est qu'au fond, les widgets Stateful et Stateless se comportent de la même manière. Ils se reconstruisent à chaque trame, la différence étant que le StatefulWidget possède un objet State qui stocke les données d'état à travers les trames et les restaure.

En cas de doute, rappelez-vous toujours cette règle : si un widget change (l'utilisateur interagit avec lui, par exemple), il est "stateful". Toutefois, si un enfant réagit aux changements, le parent qui le contient peut toujours être un widget sans état si le parent ne réagit pas aux changements.

17voto

Ulearn Points 97

Comme mentionné dans les documents de Flutter

Quel est l'intérêt ?

Certains widgets sont avec état, d'autres sans état. Si un widget change - l'utilisateur interagit avec lui, par exemple -, il a un état. L'état d'un widget est constitué de valeurs qui peuvent changer, comme la valeur actuelle d'un curseur ou le fait qu'une case à cocher soit cochée. L'état d'un widget est stocké dans un objet State, ce qui sépare l'état du widget de son apparence. Lorsque l'état du widget change, l'objet State appelle setState(), indiquant au framework de redessiner le widget.

A widget apatride n'a pas d'état interne à gérer. Icon, IconButton et Text sont des exemples de widgets sans état, qui sous-classent StatelessWidget.

A widget dynamique est dynamique. L'utilisateur peut interagir avec un widget dynamique (en saisissant des données dans un formulaire ou en déplaçant un curseur, par exemple), ou bien le widget change au fil du temps (un flux de données peut entraîner la mise à jour de l'interface utilisateur). Les cases à cocher, les radios, les curseurs, les puits d'encre, les formulaires et les champs de texte sont des exemples de widgets dynamiques, qui dépendent de StatefulWidget.

https://flutter.io/tutorials/interactive/#stateful-stateless

11voto

Krunal Points 33551

L'état est une information qui (1) peut être lue de manière synchrone lorsque le widget est construit et (2) peut changer pendant la durée de vie du widget. Il est de la responsabilité de l'implémenteur du widget de s'assurer que l'état est rapidement notifié lorsque cet état change, en utilisant State.setState.

StatefulWidget :

Un widget à état est un widget qui décrit une partie de l'interface utilisateur en construisant une constellation d'autres widgets qui décrivent plus concrètement l'interface utilisateur. Le processus de construction se poursuit de manière récursive jusqu'à ce que la description de l'interface utilisateur soit totalement concrète (par exemple, elle est entièrement constituée de RenderObjectWidgets, qui décrivent des RenderObjects concrets).

Les widgets à état sont utiles lorsque la partie de l'interface utilisateur que vous décrivez peut changer dynamiquement, par exemple parce qu'elle a un état interne commandé par une horloge ou qu'elle dépend d'un état du système. Pour les compositions qui dépendent uniquement des informations de configuration de l'objet lui-même et du BuildContext dans lequel le widget est gonflé, envisagez d'utiliser StatelessWidget.

Les instances StatefulWidget elles-mêmes sont immuables et stockent leur état mutable soit dans des objets State distincts qui sont créés par la méthode createState, soit dans des objets auxquels cet état s'abonne, par exemple des objets Stream ou ChangeNotifier, dont les références sont stockées dans des champs finaux sur le StatefulWidget lui-même.

StatelessWidget :

Un widget sans état est un widget qui décrit une partie de l'interface utilisateur en construisant une constellation d'autres widgets qui décrivent plus concrètement l'interface utilisateur. Le processus de construction se poursuit de manière récursive jusqu'à ce que la description de l'interface utilisateur soit totalement concrète (par exemple, elle est entièrement constituée de RenderObjectWidgets, qui décrivent des RenderObjects concrets).

Les widgets sans état sont utiles lorsque la partie de l'interface utilisateur que vous décrivez ne dépend de rien d'autre que des informations de configuration de l'objet lui-même et du BuildContext dans lequel le widget est gonflé. Pour les compositions qui peuvent changer dynamiquement, par exemple parce qu'elles ont un état interne commandé par une horloge ou qu'elles dépendent d'un état du système, envisagez d'utiliser StatefulWidget.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X