web-dev-qa-db-fra.com

Quelle est la relation entre les widgets stateful et stateless dans Flutter?

Un widget avec état est défini comme tout widget dont l'état change au cours de sa durée de vie. Mais c’est une pratique très courante pour un StatelessWidget d’avoir un StatefulWidget parmi ses enfants. StatelessWidget ne devient-il pas un état s'il a StatefulWidget l'un de ses enfants?

J'ai essayé de regarder la documentation dans le code de StatelessWidget, mais je ne pouvais pas comprendre comment un StatelessWidget pouvait avoir Statefulwidget comme enfants et rester toujours StatelessWidget.

Quelle est la relation et la différence entre les widgets stateful et stateless dans Flutter?

50
user462455

Un StatelessWidget ne sera jamais reconstruit ​​par lui-même (mais peut à partir d'événements externes). Un StatefulWidget peut. C'est la règle d'or.

MAIS n’importe quel type de widget peut être repeint ​​à n’importe quel moment.

Stateless signifie uniquement que toutes ses propriétés sont immuable et que le seul moyen de les modifier est de créer une nouvelle instance de ce widget. Ce n'est pas le cas par exemple verrouille l'arborescence des widgets.

Mais vous ne devriez pas vous soucier du type de vos enfants. Cela n'a aucun impact sur vous.

47
Rémi Rousselet

De la documentation à flutter.io :

... Il est important de noter ici que les widgets Stateless et Stateful se comportent de la même manière. Ils reconstruisent chaque image, à la différence que StatefulWidget a un objet State qui stocke les données d’état sur des images et les restaure.

Si vous avez des doutes, souvenez-vous toujours de cette règle: si un widget change (par exemple, il interagit avec lui), il est dynamique. Toutefois, si un enfant réagit au changement, le parent qui le contient peut toujours être un widget sans état si le parent ne réagit pas.

17
Saeed Jassani

StatefulWidget vs StatelessWidget.

enter image description here

StatelessWidget : - Un widget ne nécessitant pas d'état mutable.

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

  • Le widget stateless est utile lorsque la partie de l'interface utilisateur que vous décrivez ne dépend pas des informations de configuration contenues dans l'objet lui-même et du BuildContext dans lequel le widget est gonflé. Pour les compositions pouvant changer dynamiquement, par ex. En raison de l'état de l'horloge interne, ou en fonction de l'état du système, utilisez 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 dont l'état est modifiable.

  • Les widgets avec état sont utiles lorsque la partie de l'interface utilisateur que vous décrivez peut changer de manière dynamique.

Lorsqu'un Flutter crée un StatefulWidget, il crée un objet State. Cet objet est l'endroit où tout l'état mutable pour ce widget est maintenu.

La notion d'état est définie 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 états doivent être établis au moment où la méthode de génération est appelée).

Cycle de vie de StatefulWidget

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

1 - createState () : - Lorsque Flutter est chargé de créer un état de parcours dynamique, il appelle immédiatement createState().

  • Crée l'état mutable pour ce widget à un emplacement donné dans l'arborescence.

  • 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();

2 - monté == true : - Tous les widgets ont une propriété bool this.mounted. Il devient vrai lorsque la buildContext est affectée. C'est une erreur d'appeler setState lorsqu'un widget est démonté. Si cet objet State est actuellement dans un arbre.

  • Après avoir créé un objet State et avant d'appeler initState, le cadre "monte" l'objet State en l'associant à un objet
    BuildContext. L'objet State reste monté jusqu'à ce que le cadre
    appelle dispose(), après quoi le framework ne demandera jamais au
    Objet d'état à reconstruire.

  • C'est une erreur d'appeler setState sauf si mount est true.

bool get mounted => _element != null;

3 - initState () : - Il s'agit de la première méthode appelée lors de la création du widget (après le constructeur de la classe, bien entendu).

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

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

  • Initialisez les propriétés qui dépendent de ces widgets ‘parent’ dans l’arborescence.

  • Abonnez-vous à Streams, ChangeNotifiers ou à tout autre objet susceptible de modifier les données de ce widget.

@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}

4 - 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 à partir de cette méthode.

  • Les sous-classes remplacent rarement cette méthode, car la structure appelle toujours build après les modifications de dépendance. Certaines sous-classes remplacent cette méthode car elles doivent effectuer un travail coûteux (par exemple, des extractions réseau) lorsque leurs dépendances changent et que ce travail serait trop coûteux à effectuer pour chaque génération.

@protected
@mustCallSuper
void didChangeDependencies() { }

5 - build () : - Décrit la partie de l'interface utilisateur représentée par le widget.

Le framework appelle cette méthode dans différentes situations:

  • Après avoir appelé initState.
  • Après avoir appelé didUpdateWidget.
  • Après avoir reçu un appel à setState.
  • Une fois la dépendance de cet objet d'état modifiée (par exemple, un InheritedWidget référencé par les modifications de construction précédentes).
  • Après l'appel, désactivez puis réinsérez l'objet State dans l'arborescence à un autre emplacement.
  • 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, selon que le widget renvoyé par cette méthode peut mettre à jour la racine du sous-arbre existant. , comme déterminé en appelant Widget.canUpdate.

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

@override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }

6 - didUpdateWidget () : - Appelé chaque fois que la configuration du widget est modifiée.

  • Si le widget parent est reconstruit et demande que cet emplacement de l'arborescence soit mis à jour pour afficher un nouveau widget avec le même type d'exécution et Widget.key, le framework mettra à jour la propriété du widget de cet objet State pour faire référence au nouveau widget, puis appellera ce méthode avec le widget précédent comme argument.

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

  • La structure appelle toujours les versions après l’appel de didUpdateWidget, ce qui signifie que tous les appels de setState dans didUpdateWidget sont redondants.

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }

7 - setState () : - Chaque fois que vous modifiez l'état interne d'un objet State, modifiez la fonction que vous passez à setState:

  • Calling setState indique au framework que l'état interne de cet objet a changé de manière à affecter l'interface utilisateur de cette sous-arborescence, ce qui oblige le framework à planifier une construction pour
    Cet objet d'état.

  • Si vous modifiez simplement l'état directement sans appeler setState , il est possible que le framework ne planifie pas de construction et que l'interface utilisateur de ce sous-arbre ne soit pas mise à jour pour refléter le nouvel état.

setState(() { _myState = newValue });

8 - deactivate () : - Deactivate est appelé lorsque State est supprimé de l'arborescence, mais il peut être réinséré avant la fin du changement d'image actuel. Cette méthode existe essentiellement parce que les objets d'état peuvent être déplacés d'un point de l'arborescence à un autre.

  • Le framework appelle cette méthode chaque fois qu'il supprime cet objet State de l'arborescence. Dans certains cas, le cadre réinsérera l’objet State dans une autre partie de l’arbre (par exemple, si la sous-arborescence contenant cet objet State est greffée d’un emplacement de l’arbre à un autre). Si cela se produit, le framework veillera à ce qu'il appelle build pour donner à l'objet State une chance de s'adapter à son nouvel emplacement dans l'arborescence. Si le framework réinsère ce sous-arbre, il le fera avant la fin de l'image d'animation dans laquelle le sous-arbre a été supprimé 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 de disposition.

Ceci est rarement utilisé.

@protected
@mustCallSuper
void deactivate() { }

9 - dispose () : - Appelé lorsque cet objet est supprimé définitivement de l'arborescence.

  • Le framework appelle cette méthode lorsque cet objet State ne sera plus jamais compilé. Une fois que l'infrastructure a appelé dispose(), l'objet State est considéré comme non monté et la propriété montée est false. C'est une erreur d'appeler setState à ce stade. Cette étape du cycle de vie est terminale: il n’existe aucun moyen de remonter un objet State supprimé.

  • Les sous-classes doivent remplacer 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, allez iciici , ici

14
Farhana

L'état est une information qui (1) peut être lue de manière synchrone lors de la construction du widget et (2) peut changer pendant la durée de vie du widget. Il est de la responsabilité du réalisateur du widget de s’assurer que l’État est averti rapidement lorsque cet état change, à l’aide de State.setState.

StatefulWidget :

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

Les widgets avec état sont utiles lorsque la partie de l'interface utilisateur que vous décrivez peut changer de manière dynamique, par exemple. en raison de l’état interne de l’horloge ou de certains états du système. Pour les compositions qui dépendent uniquement des informations de configuration contenues dans 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 créés par la méthode createState, soit dans des objets auxquels cet état est abonné, par exemple des objets Stream ou ChangeNotifier, pour lesquels des références sont stockées dans les champs finaux de la commande StatefulWidget. lui-même.

StatelessWidget :

Un widget sans état est un widget qui décrit une partie de l'interface utilisateur en créant une constellation d'autres widgets décrivant l'interface utilisateur plus concrètement. Le processus de construction se poursuit de manière récursive jusqu'à ce que la description de l'interface utilisateur soit complètement concrète (par exemple, entièrement composé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 pas des informations de configuration contenues dans l'objet lui-même et du BuildContext dans lequel le widget est gonflé. Pour les compositions pouvant changer dynamiquement, par ex. en raison de l’état interne de l’horloge, ou en fonction de l’état du système, envisagez d’utiliser StatefulWidget.

10
Krunal

Comme mentionné dans les docs Flutter

À quoi ça sert?

Certains widgets sont à états et d'autres sont sans état. Si un widget change - l'utilisateur interagit avec, par exemple - il est dynamique. L’état d’un widget consiste en des valeurs qui peuvent changer, telles que la valeur actuelle d’un curseur ou si une case à cocher est cochée. L'état d'un widget est stocké dans un objet State, séparant l'état du widget de son apparence. Lorsque l'état du widget change, l'objet state appelle setState (), en demandant au framework de redessiner le widget.

Un widget sans état n'a pas d'état interne à gérer. Icon, IconButton et Text sont des exemples de widgets sans état, dans lesquels la sous-classe StatelessWidget.

Un widget avec état est dynamique. L'utilisateur peut interagir avec un widget dynamique (en le saisissant dans un formulaire ou en déplaçant un curseur, par exemple), ou bien il change au fil du temps (un flux de données peut mettre à jour l'interface utilisateur). Les cases à cocher, Radio, Curseur, InkWell, Form et TextField sont des exemples de widgets stateful, dont la sous-classe StatefulWidget.

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

8
Ulearn

question de StackOverflow sur l'étatfulness vs apatride .

Dans Flutter, la différence est que les widgets sans état peuvent être définis par tous les arguments du constructeur uniquement. Si vous créez deux widgets sans état en utilisant les mêmes arguments, ils seront identiques.

Un widget avec état, cependant, n'est pas nécessairement identique à un autre construit avec les mêmes arguments de constructeur. Ce pourrait être dans un état différent.
En réalité, un widget avec état est immuable (sans état), mais Flutter gère un état séparé object et l’associe au widget, comme expliqué dans le doc. StatefulWidget . Cela signifie que lorsque Flutter reconstruit un widget avec état, il vérifie s'il doit réutiliser un objet d'état précédent et associe, si vous le souhaitez, cet objet d'état au widget.

Le widget parent est sans état car il ne se soucie pas de l'état de son enfant. L'enfant à états lui-même (ou techniquement Flutter) prendra soin de son propre état.
De manière générale, je suis d’accord sur le fait que cela rend le widget parent d’état, car deux parents pourraient contenir deux enfants avec des états différents et donc être techniquement différents eux-mêmes. Mais du point de vue de Flutter, il construit le widget parent sans se soucier de l'état et ce n'est que lors de la construction que l'enfant tiendra compte de son état.

5
J0hj0h

Widgets sans état sont des widgets statiques. Il vous suffit de passer quelques propriétés avant d’initialiser les widgets Stateless. Ils ne dépendent d'aucun changement de données ni d'aucun changement de comportement. Par exemple. Text, Icon, RaisedButton sont des widgets sans état.

Widgets avec état sont des widgets dynamiques, ils peuvent être mis à jour pendant l'exécution en fonction de l'action de l'utilisateur ou de la modification des données. Si un widget peut changer d'état pendant l'exécution, ce sera un widget avec état.

Editer le 15/11/2018

Stateless Widgets peut effectuer un nouveau rendu si les données d'entrée/externes étaient modifiées (les données externes étant des données transmises par le constructeur). Étant donné que les widgets sans état n'ont pas d'état, ils seront rendus une fois et ne se mettront pas à jour, mais le seront uniquement lorsque des données externes seront modifiées.

Considérant que Widgets avec état ont un état interne et peuvent être rendus à nouveau si les données d'entrée changent ou si l'état du widget change.

Les widgets sans état et avec état ont un cycle de vie différent.

5
Hammad Tariq