Skip to content
Related Articles

Related Articles

Flutter – Inherited Widget

View Discussion
Improve Article
Save Article
Like Article
  • 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:

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.


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!