In This Article

InheritedWidget in Flutter: Building Robust and Dynamic Flutter UIs

Among the various state management solutions, one that often goes underappreciated is the Inherited Widget. It’s a robust, efficient, and flexible technique, largely built into the Flutter framework.

InheritedWidget in Flutter is a special widget designed to propagate information down the widget tree efficiently.

Besides provider and flutter riverport, getting a deep understanding of what an inherited widget is and how to use the inherited widget in Flutter is very crucial at the Developer’s end to create complex UIs.

Let’s get started with it.

What is an Inherited Widget in Flutter?

Inherited Widgets are a vital component of Flutter’s Widget system, providing a powerful and efficient way of passing data down the tree. The fundamental idea behind InheritedWidget is to provide a way to access data from a parent widget to one or more descendant widgets without passing the state down through constructor parameters.

It leverage dart’s object-oriented capabilities and Flutter’s reactive UI updates to create a flexible, intuitive, and performant state management system.

How to Use Inherited Widget Flutter Example

Inherited Widgets create a data layer their descendants can access via their context. The data isn’t stored in the Inherited Widget itself but in a separate model class that the Inherited Widget takes as a parameter.

  • First, we’ll create our InheritedWidget: ThemeColor is an InheritedWidget with a color property in this snippet.
class ThemeColor extends InheritedWidget {
 final Color color;

 const ThemeColor({Key? key, required this.color, required Widget child})
     : super(child: child, key: key);

 @override
 bool updateShouldNotify(ThemeColor oldWidget) {
   return color != oldWidget.color;
 }

 static ThemeColor? of(BuildContext context) {
   return context.dependOnInheritedWidgetOfExactType<ThemeColor>();
 }
}
  • Next, we’ll create the widget: that uses this ThemeColor: In this Box widget, we are accessing the color from our ThemeColor InheritedWidget and applying it to the Container.
class Box extends StatelessWidget {
 const Box({super.key});

 @override
 Widget build(BuildContext context) {
   final color = ThemeColor.of(context)?.color ?? Colors.black;
   return Container(
     width: 100,
     height: 100,
     color: color,
   );
 }
}

  • Now, we use these widgets in our main application: In the below snippet, we’re wrapping our Scaffold with the ThemeColor InheritedWidget and setting the color to Colors.red. Then, within the Box widget, we access the ThemeColor InheritedWidget and apply the color to our box.
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 const MyApp({Key? key}) : super(key: key);

 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: ThemeColor(
       color: Colors.red,
       child: Scaffold(
         appBar: AppBar(),
         body: const Center(child: Box()),
       ),
     ),
   );
 }
}

This is a simple example of how to use InheritedWidget to pass down data (in this case, a color) to descendant widgets in Flutter.

Inherited Widget Vs. Provider

Features  Inherited Widget Flutter 
Complexity Complex Simple
State Managment Propagates Data Handles State changes and listener Notifications
Multi Provider Capability No Built-in. Have to Set it Manually Has ‘multi provider’ widget
Lifecycle Management Manual Built-in
Performance Good Optimized

What is the Difference Between InheritedWidget and Inherited Model?

InheritedWidget and InheritedModel are Flutter classes that propagate information down the widget tree. However, they have a key difference in determining when to notify dependents of changes.

When an InheritedWidget changes, based on its updateShouldNotify method, it will notify all dependent widgets in the tree, and those widgets will rebuild.

Whereas the InheritedModel will only notify those dependent widgets related to the changed aspects, leading to potentially fewer widget rebuilds.

Flutter InheritedWidget with ChangeNotifier

ChangeNotifier is a class provided by Flutter that can be used with InheritedWidget to manage the state. It provides a way to listen for changes to a model and allows all listeners (typically widgets) to update their state accordingly.

An InheritedWidget provides a way to share data across the widget tree, and a ChangeNotifier provides a way to listen for changes to that data. They can help efficiently manage and respond to changes in your application’s state when used together.

👉 Inkwell flutter widget

Example: How to Use ChangeNotifier with InheritedWidget

  • Let’s define a simple ChangeNotifier: In the Counter class mentioned below, notifyListeners() is called whenever the count changes. This will trigger any listeners of this ChangeNotifier to rebuild.
class Counter with ChangeNotifier {
  int _count = 0;
  
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners();
  }
}
  • Now, let’s create our InheritedNotifier: Here, InheritedNotifier is a specialized kind of InheritedWidget that works well with ChangeNotifier. It automatically calls updateShouldNotify when the ChangeNotifier calls notifyListeners, causing the widgets listening to this InheritedNotifier to rebuild.
class CounterInheritedNotifier extends InheritedNotifier<Counter> {
 const CounterInheritedNotifier({
   super.key,
   required Widget child,
   required Counter notifier,
 }) : super(child: child, notifier: notifier);

 static CounterInheritedNotifier? of(BuildContext context) {
   return context
       .dependOnInheritedWidgetOfExactType<CounterInheritedNotifier>();
 }
}
  • Finally, you could use your CounterInheritedNotifier in your widget tree like this:
Counter _counter = Counter();

CounterInheritedNotifier(
  notifier: _counter,
  child: YourWidgetTree(),
);
  • Then in any descendant widget, you could access the counter and increment it like this:
final counterInheritedNotifier = CounterInheritedNotifier.of(context);
final counter = counterInheritedNotifier?.notifier;
final count = counter?.count ?? 0;

ElevatedButton(
 onPressed: counter?.increment,
 child: const Text('Increment'),
)

In this setup, when you call the counter.increment, it updates the count and then calls notifyListeners, triggering updateShouldNotify in the InheritedNotifier, causing all widgets to listen to the InheritedNotifier to rebuild.

Here is a visual representation of the above-mentioned code:

3 Key Features of Flutter Inherited Widget

You might be aware of the common technicalities; the following are some ways where you could increase the efficiency of the inherited widget

  • Automatic Rebuilds

If the inherited data changes, InheritedWidget will immediately rebuild dependent widgets. Because of this, updating the UI in response to changes in the shared state is simple and doesn’t need manually handle state dependencies and trigger updates. The UI will accurately reflect the most recent state of the application since the widgets that rely on the inherited data will be effectively regenerated.

  • Ancestor Access

It is another hidden gem that can aid with more advanced use cases. Widgets can access their ancestor Inherited Widgets to retrieve data. This feature can be handy when dealing with nested data models or scoped themes.

  • Querying Multiple Inherited Widgets

While Inherited Widgets are great for passing data down the tree, they can also query data up the tree. This unique feature is useful when accessing multiple data models within the same widget.

MyDataModel1 model1 = MyInheritedWidget1.of(context).myData;
MyDataModel2 model2 = MyInheritedWidget2.of(context).myData;

Conclusion

Understanding InheritedWidget is vital, as it is a cornerstone to mastering Flutter’s state management systems. It offers high flexibility, simplicity, and performance, making it a valuable tool for developers. If you are still unclear and require expert assistance in Flutter development, don’t hesitate to contact us—we’re here to help!

Picture of Bashir Ahmad

Bashir Ahmad

When not savoring tortillas, Bashir captivates readers with helpful and engaging prose, driven by his passion for Flutter and a dedication to providing value.

Share on:

Leave a Comment

Your email address will not be published. Required fields are marked *