Deprecate findChildIndexCallback in favor of findItemIndexCallback in ListView
and SliverList separated constructors
The findChildIndexCallback parameter in ListView.separated and SliverList.separated have been deprecated in favor of findItemIndexCallback.
Summary
#
The findChildIndexCallback parameter in ListView.separated and
SliverList.separated constructors have been deprecated in favor of
findItemIndexCallback. The new callback returns item indices directly,
eliminating the need for manual index calculations to account for separators.
Background
#
In ListView.separated and SliverList.separated constructors,
the findChildIndexCallback was used to locate widgets by their key.
However, this callback returned child indices, which include both items
and separators in the internal widget tree. This meant that developers had to
multiply item indices by 2 to get the correct child index, creating
confusion and error-prone code.
The new findItemIndexCallback parameter simplifies this by working
directly with item indices, which do not include separators.
This makes the API more intuitive and reduces the likelihood of
index calculation errors.
If you use the deprecated findChildIndexCallback parameter,
you will see a deprecation warning:
'findChildIndexCallback' is deprecated and shouldn't be used.
Use findItemIndexCallback instead.
findChildIndexCallback returns child indices (which include separators),
while findItemIndexCallback returns item indices (which do not).
If you were multiplying results by 2 to account for separators,
you can remove that workaround when migrating to findItemIndexCallback.
This feature was deprecated after v3.37.0-1.0.pre.
Additionally, if you try to provide both parameters, you will encounter an assertion error:
Cannot provide both findItemIndexCallback and findChildIndexCallback.
Use findItemIndexCallback as findChildIndexCallback is deprecated.
Migration guide
#
To migrate from findChildIndexCallback to findItemIndexCallback,
replace the parameter name and remove any index multiplications
that were used to account for separators.
Code before migration:
ListView.separated(
itemCount: items.length,
findChildIndexCallback: (Key key) {
final ValueKey<String> valueKey = key as ValueKey<String>;
final int itemIndex = items.indexOf(valueKey.value);
// Multiply by 2 to account for separators
return itemIndex == -1 ? null : itemIndex * 2;
},
itemBuilder: (BuildContext context, int index) {
return ListTile(
key: ValueKey<String>(items[index]),
title: Text(items[index]),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
Code after migration:
ListView.separated(
itemCount: items.length,
findItemIndexCallback: (Key key) {
final ValueKey<String> valueKey = key as ValueKey<String>;
final int itemIndex = items.indexOf(valueKey.value);
// Return item index directly - no need to multiply by 2
return itemIndex == -1 ? null : itemIndex;
},
itemBuilder: (BuildContext context, int index) {
return ListTile(
key: ValueKey<String>(items[index]),
title: Text(items[index]),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
The same migration applies to SliverList.separated:
Code before migration:
SliverList.separated(
itemCount: items.length,
findChildIndexCallback: (Key key) {
final ValueKey<String> valueKey = key as ValueKey<String>;
final int itemIndex = items.indexOf(valueKey.value);
return itemIndex == -1 ? null : itemIndex * 2;
},
itemBuilder: (BuildContext context, int index) {
return Container(
key: ValueKey<String>(items[index]),
child: Text(items[index]),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
Code after migration:
SliverList.separated(
itemCount: items.length,
findItemIndexCallback: (Key key) {
final ValueKey<String> valueKey = key as ValueKey<String>;
final int itemIndex = items.indexOf(valueKey.value);
return itemIndex == -1 ? null : itemIndex;
},
itemBuilder: (BuildContext context, int index) {
return Container(
key: ValueKey<String>(items[index]),
child: Text(items[index]),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
Timeline
#
Landed in version: 3.38.0-1.0.pre
In stable release: Not yet
References
#API documentation:
Relevant PRs:
Unless stated otherwise, the documentation on this site reflects Flutter 3.38.1. Page last updated on 2025-12-9. View source or report an issue.