When you insert/remove/reorder (or do any other manipulation) ListView items according to the default behaviour of ListView.builder and ListView.separated it always rebuilds the whole widget.
How can I avoid this? It brings undesired results such as loss of data.
Instead of using ListView.builder or ListView.separated you can use ListView.custom by setting findChildIndexCallback property
ListView.custom(
key: Key('messageListView'),
controller: _scrollController,
reverse: true,
childrenDelegate: SliverChildBuilderDelegate(
(context, i) {
return Container(key: ValueKey('message-${message.id}'));
},
childCount: _messages.length,
findChildIndexCallback: (key) {
final ValueKey<String> valueKey = key;
return _messages
.indexWhere((m) => 'message-${m.id}' == valueKey.value);
},
),
);
TL:DR: I recommend switching from ListView to a Column and wrapping the Column into a SingleChildScrollView.
I’ve been using Flutter Hooks to build animations into stateless widgets.
I’ve ran into the same problem as OP, widgets are rebuilt when entering screen and the animations run again every time they are built.
If you have a very long list of items, let me say I don’t have a great solution for you, given the extensive optimizations built into ListView.
But if you have a small list, I recommend switching from ListView to a Column and wrapping the Column into a SingleChildScrollView. For me it fixed the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With