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.