Inherited widget is a base class that allows those classes to extend the information under the tree from it. Inherited widgets are also a kind of state management technique. It works by telling registered build references when a change occurs.
You have multiple widgets nested in a widget tree, and you are trying to access the data which is somewhere up the tree. We could propagate the data through the constructor, but isn’t that cumbersome, so the inherited widget comes into the picture.
If your widget tree is a child of an inherited widget, then you can access the data anywhere in the widget tree.
Let’s see an example of using InheritedWidget, using the counter application that is generated when you create a new flutter project.
We create a new file called inherited_counter.dart, inside that file, we create a class called InheritedCounter:
class InheritedCounter extends InheritedWidget {
InheritedCounter({Key? key, required this.child,required this.counter}) : super(key: key, child: child);
final int counter;
final Widget child;
static InheritedCounter? of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<InheritedCounter>();
}
@override
bool updateShouldNotify(InheritedCounter oldWidget) {
return oldWidget.counter != counter;
}
}
As you can see the child widget is required since the InheritedWidget has to be at the root of the widget tree so it can send the data through the widget tree.
The of(context) static method is used to get access to the instance of InheritedCounter, as you can see inside that method we use context.dependOnInheritedWidgetOfExactType<InheritedCounter>(); which will let used to obtain an instance of the InheritedCounter, and registers the build context with the widget such that when that widget changes, this build context is rebuilt so that it can obtain new values from that widget.
The updateShouldNotify method which we override will notify the widgets using the InheritedWidget if they need to rebuild or not. Therefore if this method returns true then for example the StatelessWidgets using this InheritedWidget will rebuild again.
now inside the main.dart file we can do the following:
@override
Widget build(BuildContext context) {
return InheritedCounter(
counter: 5,
child: Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Builder(builder: (context) {
return Text('${InheritedCounter.of(context)!.counter}');
}),
],
),
),
),
);
}
}
In the above code, we use the InheritedCounter at the root of the widget tree, assign 5 to the counter property, and assign the Scaffold widget to the child property.
Then to access the counter property inside the Text() widget, we call the of() method that will return an instance of InheritedCounter and then call the property counter. The following code InheritedCounter.of(context) is the same as when you use MediaQuery.of(context) or Theme.of(context) both of those widgets are using InheritedWidget.
Since the InheritedWidget is immutable then to update the state (in this case counter value), we need to wrap this InheritedWidget with a StatefulWidget which will store the mutable state inside the state object.