Skip to content

Commit 9517b90

Browse files
committed
docs: add migration guide for findChildIndexCallback of seperated builders
1 parent 37db8f7 commit 9517b90

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

src/content/release/breaking-changes/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ They're sorted by release and listed in alphabetical order:
4141
* [`$FLUTTER_ROOT/version` replaced by `$FLUTTER_ROOT/bin/cache/flutter.version.json`][]
4242
* [Stop generating `AssetManifest.json`][]
4343
* [Deprecate `TextField.canRequestFocus`][]
44+
* [Deprecated findChildIndexCallback for separated constructors][]
4445

4546
[`FontWeight` also controls the weight attribute of variable fonts]: /release/breaking-changes/font-weight-variation
4647
[UISceneDelegate adoption]: /release/breaking-changes/uiscenedelegate
4748
[Stop generating `AssetManifest.json`]: /release/breaking-changes/asset-manifest-dot-json
4849
[`$FLUTTER_ROOT/version` replaced by `$FLUTTER_ROOT/bin/cache/flutter.version.json`]: /release/breaking-changes/flutter-root-version-file
4950
[Deprecate `TextField.canRequestFocus`]: /release/breaking-changes/can-request-focus
51+
[Deprecated findChildIndexCallback for separated constructors]: /release/breaking-changes/separated-builder-find-child-index-callback
5052

5153
<a id="released-in-flutter-338" aria-hidden="true"></a>
5254
### Released in Flutter 3.38
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
title: Deprecated findChildIndexCallback for separated constructors
3+
description: >-
4+
The findChildIndexCallback parameter in ListView.separated and
5+
SliverList.separated has been deprecated in favor of findItemIndexCallback.
6+
---
7+
8+
## Summary
9+
10+
The `findChildIndexCallback` parameter in `ListView.separated` and
11+
`SliverList.separated` constructors has been deprecated in favor of
12+
`findItemIndexCallback`. The new callback returns item indices directly,
13+
eliminating the need for manual index calculations to account for separators.
14+
15+
## Background
16+
17+
In `ListView.separated` and `SliverList.separated` constructors,
18+
the `findChildIndexCallback` was used to locate widgets by their key.
19+
However, this callback returned child indices, which include both items
20+
and separators in the internal widget tree. This meant developers had to
21+
multiply item indices by 2 to get the correct child index, creating
22+
confusion and error-prone code.
23+
24+
The new `findItemIndexCallback` parameter simplifies this by working
25+
directly with item indices, which do not include separators.
26+
This makes the API more intuitive and reduces the likelihood of
27+
index calculation errors.
28+
29+
If you use the deprecated `findChildIndexCallback` parameter,
30+
you will see a deprecation warning:
31+
32+
```
33+
'findChildIndexCallback' is deprecated and shouldn't be used.
34+
Use findItemIndexCallback instead.
35+
findChildIndexCallback returns child indices (which include separators),
36+
while findItemIndexCallback returns item indices (which do not).
37+
If you were multiplying results by 2 to account for separators,
38+
you can remove that workaround when migrating to findItemIndexCallback.
39+
This feature was deprecated after v3.37.0-1.0.pre.
40+
```
41+
42+
Additionally, if you try to provide both parameters, you will encounter
43+
an assertion error:
44+
45+
```
46+
Cannot provide both findItemIndexCallback and findChildIndexCallback.
47+
Use findItemIndexCallback as findChildIndexCallback is deprecated.
48+
```
49+
50+
## Migration guide
51+
52+
To migrate from `findChildIndexCallback` to `findItemIndexCallback`,
53+
replace the parameter name and remove any index multiplications
54+
that were used to account for separators.
55+
56+
Code before migration:
57+
58+
```dart
59+
ListView.separated(
60+
itemCount: items.length,
61+
findChildIndexCallback: (Key key) {
62+
final ValueKey<String> valueKey = key as ValueKey<String>;
63+
final int itemIndex = items.indexOf(valueKey.value);
64+
// Multiply by 2 to account for separators
65+
return itemIndex == -1 ? null : itemIndex * 2;
66+
},
67+
itemBuilder: (BuildContext context, int index) {
68+
return ListTile(
69+
key: ValueKey<String>(items[index]),
70+
title: Text(items[index]),
71+
);
72+
},
73+
separatorBuilder: (BuildContext context, int index) => const Divider(),
74+
)
75+
```
76+
77+
Code after migration:
78+
79+
```dart
80+
ListView.separated(
81+
itemCount: items.length,
82+
findItemIndexCallback: (Key key) {
83+
final ValueKey<String> valueKey = key as ValueKey<String>;
84+
// Return item index directly - no need to multiply by 2
85+
return items.indexOf(valueKey.value);
86+
},
87+
itemBuilder: (BuildContext context, int index) {
88+
return ListTile(
89+
key: ValueKey<String>(items[index]),
90+
title: Text(items[index]),
91+
);
92+
},
93+
separatorBuilder: (BuildContext context, int index) => const Divider(),
94+
)
95+
```
96+
97+
The same migration applies to `SliverList.separated`:
98+
99+
Code before migration:
100+
101+
```dart
102+
SliverList.separated(
103+
itemCount: items.length,
104+
findChildIndexCallback: (Key key) {
105+
final ValueKey<String> valueKey = key as ValueKey<String>;
106+
final int itemIndex = items.indexOf(valueKey.value);
107+
return itemIndex == -1 ? null : itemIndex * 2;
108+
},
109+
itemBuilder: (BuildContext context, int index) {
110+
return Container(
111+
key: ValueKey<String>(items[index]),
112+
child: Text(items[index]),
113+
);
114+
},
115+
separatorBuilder: (BuildContext context, int index) => const Divider(),
116+
)
117+
```
118+
119+
Code after migration:
120+
121+
```dart
122+
SliverList.separated(
123+
itemCount: items.length,
124+
findItemIndexCallback: (Key key) {
125+
final ValueKey<String> valueKey = key as ValueKey<String>;
126+
return items.indexOf(valueKey.value);
127+
},
128+
itemBuilder: (BuildContext context, int index) {
129+
return Container(
130+
key: ValueKey<String>(items[index]),
131+
child: Text(items[index]),
132+
);
133+
},
134+
separatorBuilder: (BuildContext context, int index) => const Divider(),
135+
)
136+
```
137+
138+
## Timeline
139+
140+
Landed in version: 3.38.0-1.0.pre<br>
141+
In stable release: Not yet
142+
143+
## References
144+
145+
API documentation:
146+
147+
* [`ListView.separated`][]
148+
* [`SliverList.separated`][]
149+
150+
Relevant PRs:
151+
152+
* [Deprecate findChildIndexCallback for separated constructors][]
153+
154+
[`ListView.separated`]: {{site.api}}/flutter/widgets/ListView/ListView.separated.html
155+
[`SliverList.separated`]: {{site.api}}/flutter/widgets/SliverList/SliverList.separated.html
156+
[Deprecate findChildIndexCallback for separated constructors]: {{site.repo.flutter}}/pull/174491

0 commit comments

Comments
 (0)