2 votes

Pourquoi la méthode "initState()" de tous les éléments de la liste est-elle déclenchée à chaque fois qu'un nouvel élément est inséré à l'index 0 ?

Je veux ajouter un nouveau widget (StatefulWidget) au ListView, en haut de la liste. items.insert(0, listItem) mais lorsque je fais cela, tous les éléments de la liste s'initialisent à nouveau ( initState() le crochet appelle à chaque fois)

Si j'ajoute les éléments au bas de la liste items.add(listItem) - tout fonctionne comme prévu ( initState() est appelé uniquement sur l'élément nouvellement ajouté).

Code à des fins de démonstration

Code du widget ListItem

class ListItem extends StatefulWidget {
  final String label;

  const ListItem({Key key, @required this.label}) : super(key: key);

  _ListItemState createState() => _ListItemState();
}

class _ListItemState extends State<ListItem> {
  @override
  void initState() {
    super.initState();
    print('initState() ${this.widget.label}');
  }

  @override
  Widget build(BuildContext context) {
    return Text(this.widget.label);
  }
}

Code du widget de liste

L'ajout de nouveaux éléments se fait à l'intérieur de addItem() fonction :

class ItemsList extends StatefulWidget {
  State<StatefulWidget> createState() => ItemsListState();
}

class ItemsListState extends State<ItemsList> {
  var items = List<ListItem>();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        child: ListView(children: items),
        onTap: addItem);
  }

  void addItem() {
    final label = items.length.toString();
    print('Add $label');

    final listItem = ListItem(key: ValueKey(label), label: label);
    items.insert(0, listItem);

    this.setState(() {
      items = []..addAll(items);
    });
  }
}

Résultats

Sortie console lorsque addItem() a été appelée 3 fois (juste pour l'exemple) :

Add 0
initState() 0
Add 1
initState() 1
initState() 0
Add 2
initState() 2
initState() 1
initState() 0

Sortie attendue, lorsque les nouveaux éléments sont ajoutés au bas de la liste ( items.add(listItem) au lieu de items.insert(0, listItem) )

Add 0
initState() 0
Add 1
initState() 1
Add 2
initState() 2

Existe-t-il des solutions de contournement pour cette situation ? Je veux que les éléments de liste précédemment ajoutés restent dans leur ancien état.

J'ai essayé de changer la direction de l'axe de la fenêtre de la liste en up (changement reverse propriété de ListView a true ) mais j'ai obtenu le même résultat.

1voto

diegoveloper Points 24042

C'est parce que vous changez les clés de commande de vos articles.

      ListView(
            children: items,
            reverse: true,
          )

et

     final listItem = ListItem(key: ValueKey(label), label: label);
        items.add(listItem);

        this.setState(() {
          items = List.from(items);
        });

devrait fonctionner

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