A Deep Dive into Inherited Widgets in Flutter

For developers, Flutter has made it quite easy to create complex UIs. Pulsation automated testing enables you to achieve high responsiveness in your application by helping in the discovery of bugs and other problems. Pulsation is a free and open-source tool to develop code-based mobile, desktop, and web applications.

Hello everyone. In this blog, we will talk about Flutter’s inherited widget. We’ll also see a basic example of the inherited Widget and its features and also see how to use them in your Flutter application development. So, let’s begin.

Introduction of Inherited Widget

The inherited widget in Flutter is an initial class from which other classes can extend the data in the information tree. Another form of state management method is inherited widgets. When a change happens, it notifies registered build references. While doing so, it can recreate each widget at the top of the tree, but it adds interoperability to any app in a secure manner.

What are the benefits of Inherited Widget in Flutter?

Flutter’s inherited widget class is an effective tool for transferring data and state across widgets that aren’t connected directly. It serves as a base class for Flutter widgets that effectively propagate data along the tree. Here are a few of inherited widget’s main features and advantages:

1. Effective data propagation:

InheritedWidget enables effective data propagation down the widget tree, making sure that only essential widgets are rebuilt when the inherited widget itself changes state.

2. Flexible state management:

InheritedWidget gives Flutter applications a significant degree of flexibility for handling state. It provides a quick and effective way to share data among numerous widgets without the use of complex Flutter state management libraries.

3. Fallback logic:

If the widget is not present in the current scope, inheritedWidget helps you create fallback behaviors. The ‘of’ and’maybeOf’ methods, which the inheritedWidget class is capable of implementing, are used to do this.

4. Sharing theme data:

You can utilize inheritedWidget to transfer theme data throughout different parts of your application, ensuring uniform styling and theming.

5. Providing global state:

Using InheritedWidget, you may give global state to several widgets so that they can access and change shared data.

6. Implementation specifics:

In some circumstances, an inherited widget may be a particular of another class’s implementation. The ‘of’ and’maybeOf’ methods are usually implemented on the public class in these circumstances.

A key idea in Flutter’s state management systems is inheritedWidget, which gives developers a useful Flutter app development tool for creating robust and dynamic user interfaces.

Inherited widget constructor

Let’s discuss some of the main inherited widget constructors.

Code:

const InheritedWidget({ super.key, required super.child });

7. Child:

To remove numerous children, we use the child attribute with widgets like row, column stack, etc.

8. Key:

A unique parameter is the key property. In basic terms, each widget’s creator can be identified if the runtime type and key property of two widgets are equal. After updating an existing widget, a new widget refers to the updated widget as the underlying element. If not, the outdated element is updated. The new widget is transformed into an element, and the new element is then inserted into the tree once the tree has been removed from the tree.

Implementation of Code

You have to integrate it into your code accordingly:
Inside the lib folder, create a new dart file called count_state_demo.
We have developed a class called Constant that extends the inherited widget before using it. It replaces the updateShouldNotify method, which is used to find the widget that is the closest to the data from the specified BuildContext.

Code

class CountStateDemo extends InheritedWidget {
  final int count;
  final void Function() addCounter;
  final void Function() removeCounter;
  const CountStateDemo({
    super.key,
    required super.child,
    required this.count,
    required this.addCounter,
    required this.removeCounter,
  });


  static CountStateDemo? of(BuildContext context) {
    return (context.dependOnInheritedWidgetOfExactType());
  }


  @override
  bool updateShouldNotify(CountStateDemo oldWidget) {
    return count != oldWidget.count;
  }
}

Before the inherited widget’s updateShouldNotify function may be overridden, this method must be canceled. The widget received from this widget must either be notified or not; hence, this method has been utilized. It is of the Boolean type and accepts a square-like parameter.

Code

@override
  bool updateShouldNotify(CountStateDemo oldWidget) {
    return count != oldWidget.count;
  }

Now that the addCounter and removeCounter functions have been initialized and the count state in the RootWidget class has been set, we can create the InheritedWidgeDemo class, which will display the value of the counter and have two buttons that can be used to add and subtract value.

Code

return CountStateDemo(
      count: count,
      addCounter: addCounter,
      removeCounter: removeCounter,
      child: const InheritedWidgetDemo(),
    );

Output

Final Code

import 'package:flutter/material.dart';
import 'package:inherited_widget_demo/count_state_demo.dart';


class RootWidget extends StatefulWidget {
  const RootWidget({super.key});


  @override
  State createState() => _RootWidgetState();
}


class _RootWidgetState extends State {
  int count = 0;


  void addCounter() {
    setState(() {
      count++;
    });
  }


  void removeCounter() {
    setState(() {
      if (count > 0) count--;
    });
  }


  @override
  Widget build(BuildContext context) {
    return CountStateDemo(
      count: count,
      addCounter: addCounter,
      removeCounter: removeCounter,
      child: const InheritedWidgetDemo(),
    );
  }
}


class InheritedWidgetDemo extends StatelessWidget {
  const InheritedWidgetDemo({super.key});


  @override
  Widget build(BuildContext context) {
    final counterState = CountStateDemo.of(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue,
        title: const Text(
          'Counter Inherited Widget Demo',
          style: TextStyle(color: Colors.white),
        ),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Align(
            alignment: Alignment.bottomCenter,
            child: Text(
              'Items add & remove: ${counterState!.count}',
              style:const TextStyle(fontSize: 20),
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Align(
                  alignment: Alignment.bottomLeft,
                  child: FloatingActionButton(
                    onPressed: counterState.removeCounter,
                    child: const Icon(
                      Icons.remove,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Align(
                  alignment: Alignment.bottomCenter,
                  child: FloatingActionButton(
                    onPressed: counterState.addCounter,
                    child: const Icon(
                      Icons.add,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Using an inherited widget to access data

We can utilize the inherited widget in any widget below the appropriate level after first placing it there, as shown above.

context.dependOnInheritedWidgetOfExactType()!.counter.toString()

The common approach is to create a static method on the class that returns the data, and this includes the built-in Flutter inherited widgets (such as Theme or MediaQuery).

Code

class AppDataProvider  extends InheritedWidget {
  final int counter;
  const AppDataProvider({super.key,required this.counter,required super.child});
 
  static AppDataProvider? of (BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType();


  @override
  bool updateShouldNotify(covariant AppDataProvider oldWidget) {
    return oldWidget != this ;
  }
}

Schedule an interview with WordPress developers

Changing data for the inherited Widget

There is not any modification to the Inherited Widgets. As a result, we are unable to alter the values of any of the fields within them. You can use the technique mentioned above if you have static data that never changes.

We can use an object similar to this in place of primitive fields if you want the data inside the inherited widget to be modified throughout the development of the application.

Code

class AppDataProvider extends InheritedWidget {
  final AppData appData;
  const AppDataProvider(
      {super.key, required this.appData, required super.child});


  static AppDataProvider? of(BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType();


  @override
  bool updateShouldNotify(covariant AppDataProvider oldWidget) {
    return oldWidget != this;
  }
}


class AppData {
  int count;
  Color backgroundColor;
  AppData({required this.count, required this.backgroundColor});


  incrementCount() {
    count++;
  }


  changeBackgroundColor(Color bgColor) {
    backgroundColor = bgColor;
  }
}

Conclusion

In Flutter, inherited widgets provide a powerful way to communicate data across the widget tree effectively. They are particularly useful for app state management and minimizing unnecessary widget rebuilds. However, managing them in larger apps may be challenging and requires a thorough knowledge of Flutter’s widget tree.

Suppose you’re looking to implement inherited widgets or any other Flutter development tasks. In that case, you can hire a Flutter developer from a reputable Flutter app development company like Bosc Tech Labs, who has expertise in building dynamic and efficient Flutter applications. Let’s get connected!

Frequently Asked Questions (FAQs)

1. Define inherited widgets in Flutter.

With the help of Flutter’s inheritedWidget, data can be quickly transmitted down the widget tree, offering an intricate way of managing state and sharing information among various widgets.

2. What differentiates an InheritedNotifier from an InheritedWidget?

A subclass of InheritedWidget called InheritedNotifier was created with the sole objective of storing a Listenable object and updating its dependents if the data changes. It also does so effectively. Even if there are several changes between the two frames, the dependencies will only need to be rebuilt once.

3. How do inherited widgets function?

The root of a widget tree must be defined as a data source for inherited widgets to function. Any descendant widget that specifically requests access to this data using the BuildContext and the inheritedWidgets function will subsequently be able to access it.


Book your appointment now

Request a Quote