There are some confusions about InheritedWidget that I don't understand.
I have searched and read some QAs about InheritedWidget on stackoverflow, but there are still things that I don't understand.
First of all, let's create a scenario.
This is my InheritedWidget:
class MyInheritedWidget extends InheritedWidget {
final String name;
MyInheritedWidget({
@required this.name,
@required Widget child,
Key key,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) =>
oldWidget.name != this.name;
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
}
and this is MyHomePage that contains the MyInheritedWidget. MyInheritedWidget has two children: WidgetA and a button that navigates to another screen, in this case Page1.
class MyHomePage extends StatefulWidget {
@override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: MyInheritedWidget(
name: 'Name',
child: Column(
children: [
WidgetA(),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Page1(),
),
);
},
child: Text('Go to page 1'),
)
],
),
),
),
);
}
}
Inside WidgetA there is a text widget that displays the name field from MyInheritedWidget and another button that navigates to Page2.
class WidgetA extends StatefulWidget {
@override
_WidgetAState createState() => _WidgetAState();
}
class _WidgetAState extends State<WidgetA> {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Column(
children: [
Text(myInheritedWidget.name),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Page2(),
),
);
},
child: Text('Go to page 2'),
)
],
);
}
}
Page1 and Page2 each has only a text widget that displays the name field from MyInheritedWidget.
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Page 1'),
),
body: Text(myInheritedWidget.name),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
body: Text(myInheritedWidget.name),
);
}
}
In this scenario, the name field of MyInheritedWidget is not accessible form Page1 and Page2, but it can be accessed in WidgetA.
Now lets get to the question:
It is said that an InheritedWidget can be accessed from all of its descendants. What does descendant mean?
In MyHomePage, I know WidgetA is a descendant of MyInheritedWidget. but, is Page1 also a descendant of MyInheritedWidget?
If the answer is no, How can I make Page1 a descendant of MyInheritedWidget?
Do I need to wrap it again inside MyInheritedWidget?
What if there is a chain of navigations like this: Page1-> Page2 -> Page3 ... Page10 and I want to access MyInheritedWidget in Page10, Do I have to wrap each of the pages inside MyInheritedWidget?
As @pskink says,
MyHomePagepushesPage1, which is a descendant ofNavigator, which is underMaterialApp, notMyInheritedWidget. The easiest solution is to createMyInheritedWidgetaboveMaterialApp. This is my code (usingChangeNotifierProviderinstead ofMyInheritedWidget).Here is an example using multiple
Navigatorsto scope theInheritedWidget. The widgetContextWidgetcreates anInheritedWidgetand aNavigatorand has child widgets for the screens in your example.