Flutter - Inherited Widget
Last Updated :
30 May, 2022
If you are a flutter developer then you know how easy is to create Flutter UI. But when you have lots of widgets in your app and you want to pass data from one widget to another widget, this will be a pain for many developers,s especially for the newbie, this will be really hard for them to pass the data from a widget of widget tree to bottom widget. And if know about widgets there are generally two types of widgets Stateless and stateful widgets. But there is another type of widget called InheritedWidget.
InheritedWidget
The inherited widget provides us with a convenient way to pass data between widgets. While developing an app you will need some data from your parent's widgets or grant parent widgets or maybe beyond that. So if your app is small you can pass your data using the constructor of the widget class, but for a larger app, this is not an easy task. Unknowingly we have used inherited widgets in many places while developing the flutter app.Theme.of(context), MediQuery.of(context), and Navigator.of(context) (if you check the codes of Navigation you will find that).
Dart
const InheritedWidget({
Key? key, required Widget child
})
: super(key: key, child: child);
The first parameter is the key, a key is an identifier for widgets, and elements in Flutter. A new widget will only be used to update an existing widget if its key is the same as the key of the current widget associated with the element. The child parameter is of type Widget so we can pass any widget as a parameter as a child widget. Let’s create a simple example,
Dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyScreen(),
);
}
}
class MyInheritedWidget extends InheritedWidget {
const MyInheritedWidget({Key? key,required this.child,required this.message}) : super(key: key, child: child);
final Widget child;
// message of our inherited widget class
final String message;
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>()!;
}
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return oldWidget.message != message;
}
}
class MyScreen extends StatelessWidget {
const MyScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GFG"),
backgroundColor: Colors.green,
),
body: MyInheritedWidget(
// passing the message as string
message:"Hey GEEKS",
child: Builder(
builder: (BuildContext innerContext) {
return Center(
child: Text(
// using the message of our inherited widget using of()
MyInheritedWidget.of(innerContext).message,
style: const TextStyle(fontWeight: FontWeight.bold),
)
);
},
),
),
);
}
}
Output:
The inherited widget class is immutable. Here we have created a String variable called message and it’s declared as final so we can not modify it in the future. We override one method called updateShouldNotify which has a parameter old widget, this method is used to notify the widget when we rebuild the widget, For example, if the data held by this widget is the same as the data held by the old widget, then we do not need to rebuild the widgets and we don’t need to notify the widget. But the important part is the static of(), is it mandatory to define it in our inherited widget? The answer is NO. But this is a convention that we follow, you can directly call context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() and use that.
Few developers define the inherited widget as private and implement it in another class, there is no stand way of defining an inherited widget but if you look at the Theme.of(context) codes you will see it used a private InheritedWidget class.
Note: See we are using Builder() and innerContext to access the message of the inherited widget, if you use context then it won’t work. Flutter says When we use the method, the context must be a descendant of InheritedWidget, which means the context must be below the inheridWidget in the tree.
The above example is a simple example, Let’s do a complicated example,
Dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyNavigation(),
);
}
}
// route function for Routing of pages
Route generatePage(child) {
return MaterialPageRoute(builder: (context) => child);
}
class MyNavigation extends StatelessWidget {
const MyNavigation({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MyInheritedWidget(
// message as string for our inherited widget
message: 'Hey, Geekss',
child: Navigator(
onGenerateRoute: (settings) {
switch (settings.name) {
case 'screen1':
// Route for firs screen
return generatePage(const FirstScreen());
case 'screen2':
// Route for second screen
return generatePage(const SecondScreen());
}
},
// our first screen in app
initialRoute: 'screen1',
),
);
}
}
class MyInheritedWidget extends InheritedWidget {
const MyInheritedWidget({Key? key,required this.child,required this.message}) : super(key: key, child: child);
@override
final Widget child;
// message variable for
// our inherited widget
final String message;
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>()!;
}
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return true;
}
}
class FirstScreen extends StatelessWidget {
const FirstScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Geeks For Geeks'),
backgroundColor: Colors.green,
),
body: Center(
child: ElevatedButton(
// showing message variable of our
// inherotedd widget class using of()
child: Text(MyInheritedWidget.of(context).message),
onPressed: () {
Navigator.of(context)
// navigate to second screen
.push(MaterialPageRoute(builder: (_) => SecondScreen()));
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
const SecondScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Geeks For Geeks'),
backgroundColor: Colors.green,
),
body: Center(
child: Text(MyInheritedWidget.of(context).message + "\n This is second screen",style: const TextStyle(fontWeight: FontWeight.bold),),
// showing message variable of our
// inherotedd widget class using of()
)
);
}
}
Final Output:
Explanation:
In the above example, we just create two screens and use navigation, If you check the code properly you see that we create a navigation widget as a child of MyInheritedWidget. We use the message variable of MyInheritedWidget on both screens. If we don’t create a Navigation widget as a child of MyInheritedWidget, then we can not access the message variable of MyInheritedWidget. We can use InheritedWidget as a state management tool but the complexity will increase, so the flutter team recommends that for a complex and large app we should use some state management tool.
Similar Reads
RotatedBox Widget in Flutter
The RotatedBox widget is used to rotate its child by an integral number of quarter turns. It is used to orient its child widgets into either horizontal or vertical orientation. Furthermore, it is very lightweight and can be used for designing various UI as it gives flexibility to the user over the D
2 min read
Flutter - IgnorePointer Widget
IgnorePointer is a built-in widget in flutter which is similar to the AbsorbPointer widget, they both prevent their children's widget from pointer-events which are taping, clicking, dragging, scrolling, and hover. They both do the same thing in two different ways, the AbsorbPointer widget absorbs al
6 min read
Table Widget in Flutter
Table widget is used to display items in a table layout. There is no need to use Rows and Columns to create a table. If we have multiple rows with the same width of columns then Table widget is the right approach. SliverList or Column will be most suitable if we only want to have a single column. Th
3 min read
Flutter - ImageFiltered Widget
In Flutter it's straightforward to blur the background image using Image Filtered Widget. A filter operation is used to scan the image. ImageFiltered is a widget that applies ImageFilter to its children to blur the image. ImageFilter Constructorconst ImageFiltered({ Key? key, required this.imageFilt
3 min read
Flutter - RichText Widget
The RichText widget is used to display text that uses various different styles. The displayed text is described using a tree of TextSpan objects, each of which has its own associated style that is used for that subtree. Depending on the layout constraints the text might break across multiple lines o
3 min read
PageView Widget in Flutter
The PageView widget allows the user to transition between different screens in their flutter application. All you need to set it up are a PageViewController and a PageView. Constructor of PageView class:Syntax: PageView({Key key, Axis scrollDirection, bool reverse, PageController controller, ScrollP
3 min read
Opacity Widget in Flutter
The Opacity widget that makes its child partially transparent. This class colors its child into an intermediate buffer and then merges the child back into the scene partially transparent. For values of opacity other than 0.0 and 1.0, this class is relatively expensive as it needs coloring the child
2 min read
Flutter - Positioned Widget
Positioned is a widget that comes built-in with flutter SDK. Positioned does exactly what it sounds like, which is it arbitrarily positioned widgets on top of each other. It is usually used to position child widgets in Stack widget or similar. It only works for Stateless and Stateful widgets. Constr
3 min read
Flutter - InkWell Widget
InkWell is the material widget in flutter. It responds to the touch action as performed by the user. Inkwell will respond when the user clicks the button. There are so many gestures like double-tap, long press, tap down, etc. Below are the so many properties of this widget. We can set the radius of
2 min read
Flutter - ListTile Widget
The ListTile widget is used to populate a ListView in Flutter. It contains a title as well as leading or trailing icons. Let's understand this with the help of an example.The Constructor of the ListTile classListTile({ Key key, Widget leading, Widget title, Widget subtitle, Widget trailing, bool isT
4 min read