Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly use the findChildIndexCallback in ListView.builder flutter?

Tags:

flutter

dart

I am trying to use the findChildIndexCallback to keep the state of my StatefulWidgets inside a ListView.builder.

Can someone please provide an example of how can i actually "find" the Listview children ?

My question directly comes from an issue i have made and that was actually fixed by the Flutter team.

Here is my code so far that is not working :

ListView.builder(
            itemCount: model.messagesList.length,
            findChildIndexCallback: (key) {
              // final ValueKey<String> valueKey = key as ValueKey<String>;
              // return model.messagesList.indexWhere((element) => element.uid == valueKey.value); // Doesn't change anything, my widgets are all rebuilt on insert
            },
            itemBuilder: (context, index) {
              DMessage message = model.messagesList[index];
              return MessageItem(
                key: ValueKey<String>(message.uid)
                message: message
              );
            }),
like image 850
Tom3652 Avatar asked Dec 17 '25 15:12

Tom3652


1 Answers

Just use StatefulWidget along with AutomaticKeepAliveClientMixin within your item widget. Subclasses must implement wantKeepAlive, and their build methods must call super.build(BuildContext).

class ItemWidget extends StatefulWidget {
  const ItemWidget({Key? key, required this.item}) : super(key: key);

  final int item;

  @override
  State<ItemWidget> createState() => _ItemWidgetState();
}

class _ItemWidgetState extends State<ItemWidget>
    with AutomaticKeepAliveClientMixin {
  bool selected = false;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return ListTile(
      selected: selected,
      title: Text('Index-${widget.item}'),
      onTap: () {
        setState(() {
          selected = !selected;
        });
      },
    );
  }

  @override
  bool get wantKeepAlive => true;
}

And provide the findChildIndexCallback property on your ListView like below :

class ListWidget extends StatelessWidget {
  const ListWidget({Key? key, required this.items}) : super(key: key);

  final List<int> items;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (context, index) {
        final item = items[index];
        return ItemWidget(key: ValueKey(item), item: item);
      },
      itemCount: items.length,
      findChildIndexCallback: (Key key) {
        final valueKey = key as ValueKey;
        final index = items.indexWhere((item) => item == valueKey.value);
        if (index == -1) return null;
        return index;
      },
    );
  }
}

Here the dartpad https://dartpad.dev/?id=b02294906a0b0c77984126e62f5a048d.

  • Tap any items on list, so it will become selected
  • Add new item using FAB, it will insert new element into random index of listview
  • After added new item, the already selected (state) item(s) will remain selected
like image 75
Alann Maulana Avatar answered Dec 20 '25 09:12

Alann Maulana



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!