'`dependOnInheritedWidgetOfExactType` but obtain non-nearest ancestor?
Consider the following case:
MyInheritedWidget(
identity: "a",
child: MyInheritedWidget(
identity: "b",
child: MyChildWidget(),
),
)
Inside MyChildWidget, I can use context.dependOnInheritedWidgetOfExactType<MyInheritedWiget>() to get the nearest instance of MyInheritedWiget in my ancestors. Namely, the b in this case. However, I hope there exist an approach such that I can depend on the non-nearest one, a in this case.
For example, hope such API exists:
context.dependOnInheritedWidgetOfExactType<MyInheritedWiget>((widget) => widget.identity == 'a')
Or such API may also be OK:
context.findAllInheritedWidgetsOfExactType<MyInheritedWiget>().where((widget) => widget.identity == 'a')
And so on. But I cannot find an appropriate API like this...
Thanks for any suggestions!
Solution 1:[1]
Each Element holds HashMap<Type, InheritedElement>. That's why we have quick access to inherited ancestors by type. But this approach limits us to one accessible widget of given type.
Another approach is iterating parents' elements until we find one that we need. This approach is implemented in findAncestorStateOfType and findRootAncestorStateOfType and used e.g by Navigator.of and ScaffoldState.of. Note that it's O(N). We can use it to find an ancestor with given property:
extension BuildContextX on BuildContext {
Iterable<T> findAncestorStatesOfType<T extends State>() sync* {
final ancestor = findAncestorStateOfType<T>();
if (ancestor != null) {
yield ancestor;
yield* ancestor.context.findAncestorStatesOfType<T>();
}
}
}
class MyWidget extends StatefulWidget {
final String identity;
...
static MyWidgetState findWith(
BuildContext context, {
required String identity,
}) {
return context
.findAncestorStatesOfType<MyWidgetState>()
.firstWhere((state) => state.widget.identity == identity);
}
@override
State<MyWidget> createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
...
}
Use it like this:
MyWidget.findWith(context, identity: 'x')
Full example: https://dartpad.dev/?id=e66d474b5685f6a2c815040ffda0b027
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
