How to Use InheritedWidget in Flutter

What is InheritedWidget?

by Ans Ali

Flutter provides a rich set of tools to manage state across your application, and one of the most powerful among these is the InheritedWidget. It is a special kind of widget in Flutter that allows data to be shared across the widget tree efficiently.

When you want to pass data down the tree from a parent to its descendants without having to pass it explicitly through the constructor, InheritedWidget comes in handy. It enables you to build a reactive data model that automatically updates the UI whenever the shared data changes. Understanding how to use InheritedWidget can greatly improve your app’s performance and maintainability.

When to Use InheritedWidget

You should consider using InheritedWidget in the following scenarios:

Shared State

When you have data that needs to be accessed by multiple widgets but doesn’t need to be tied to a specific widget’s lifecycle.

Performance Optimisation

Since InheritedWidget only rebuilds the widgets that depend on it, it can help optimise performance, especially in large widget trees.

Decoupling Widgets

It allows for cleaner code by decoupling the widgets that produce data from those that consume it.

How to Implement InheritedWidget

Let’s walk through a simple example of how to create and use an InheritedWidget in Flutter.

Step 1: Create the InheritedWidget

First, we define our InheritedWidget. In this example, we’ll create a widget that shares a simple counter value.

import 'package:flutter/material.dart';
class Counter extends InheritedWidget {
  final int count;
  final Function() increment;
  Counter({Key? key, required this.count, required this.increment, required Widget child})
      : super(key: key, child: child);
  static Counter? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<Counter>();
  }
  @override
  bool updateShouldNotify(Counter oldWidget) {
    return count != oldWidget.count;
  }
}
Step 2: Use the InheritedWidget in Your Widget Tree

Now that we have our InheritedWidget, we can use it in our widget tree. We will wrap our app in the Counter widget to provide access to the shared state.

void main() {
  runApp(MyApp());
}
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
  int _count = 0;
  void _incrementCounter() {
    setState(() {
      _count++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Counter(
      count: _count,
      increment: _incrementCounter,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text('InheritedWidget Example'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                CountDisplay(),
                IncrementButton(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
Step 3: Access Data from InheritedWidget

Finally, we need to create the widgets that will consume the data from our InheritedWidget.

class CountDisplay extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Counter.of(context);
    return Text(
      'Count: \${counter?.count}',
      style: TextStyle(fontSize: 24),
    );
  }
}
class IncrementButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Counter.of(context);
    return ElevatedButton(
      onPressed: counter?.increment,
      child: Text('Increment'),
    );
  }
}

How It Works

State Management

The Counter widget holds the current count and the method to increment it. The increment function is called when the button is pressed.

Dependency

The CountDisplay and IncrementButton widgets use the Counter.of(context) method to access the shared state. They automatically rebuild when the count changes, thanks to the updateShouldNotify method.

Efficiency

By using InheritedWidget, we avoid passing the count and increment method down through every widget explicitly. This keeps our widget tree clean and efficient.

Wrap-Up

InheritedWidget is a powerful tool for managing state in Flutter applications. It allows for efficient data sharing across the widget tree and helps to maintain a clean architecture. While it’s not always the easiest to implement for more complex state management needs, it serves as a fundamental building block for understanding how state flows in Flutter. For larger applications, consider combining InheritedWidget with other state management solutions like Provider, Riverpod, or BLoC.

Enhance Your Flutter Skills

Stay tuned to our blog for more insights on Flutter development.

How to Use Scaffold Key in Flutter