Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/content/release/breaking-changes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ They're sorted by release and listed in alphabetical order:
* [`$FLUTTER_ROOT/version` replaced by `$FLUTTER_ROOT/bin/cache/flutter.version.json`][]
* [Stop generating `AssetManifest.json`][]
* [Deprecate `TextField.canRequestFocus`][]
* [Deprecate `findChildIndexCallback` in favor of `findItemIndexCallback` in `ListView` and `SliverList` separated constructors][]

[`FontWeight` also controls the weight attribute of variable fonts]: /release/breaking-changes/font-weight-variation
[UISceneDelegate adoption]: /release/breaking-changes/uiscenedelegate
[Stop generating `AssetManifest.json`]: /release/breaking-changes/asset-manifest-dot-json
[`$FLUTTER_ROOT/version` replaced by `$FLUTTER_ROOT/bin/cache/flutter.version.json`]: /release/breaking-changes/flutter-root-version-file
[Deprecate `TextField.canRequestFocus`]: /release/breaking-changes/can-request-focus
[Deprecate `findChildIndexCallback` in favor of `findItemIndexCallback` in `ListView` and `SliverList` separated constructors]: /release/breaking-changes/separated-builder-find-child-index-callback

<a id="released-in-flutter-338" aria-hidden="true"></a>
### Released in Flutter 3.38
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
title: Deprecate `findChildIndexCallback` in favor of `findItemIndexCallback` in `ListView` and `SliverList` separated constructors
description: >-
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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<br>
In stable release: Not yet

## References

API documentation:

* [`ListView.separated`][]
* [`SliverList.separated`][]

Relevant PRs:

* [Deprecate findChildIndexCallback for separated constructors][]

[`ListView.separated`]: {{site.api}}/flutter/widgets/ListView/ListView.separated.html
[`SliverList.separated`]: {{site.api}}/flutter/widgets/SliverList/SliverList.separated.html
[Deprecate findChildIndexCallback for separated constructors]: {{site.repo.flutter}}/pull/174491