Inherited Widgets In-depth
Hey Folks!đ
Have you ever wondered what happens behind the scenes when you write Theme.of(context)
or MediaQuery.of(context)
?đ¤ If not, then in this article, you will learn everything about InheritedWidgets along with some fun facts đ
This blog is for both beginner and experienced developers so that everyone can benefit from it. So without further a do, letâs get started đ
Table of Contents:
- Need of an Inherited Widget
- Implementation of an Inherited Widget
- Inherited Widget In-depth
- Some rules to follow
- Demo
- Conclusion
Need of an Inherited Widget
We all have heard that Everything is a widget in Flutter. While this statement is not true, we can say that Widget plays a crucial role while developing apps in Flutter.
In Flutter, thereâre so many types of widgets such as StateLessWidget
, StatefulWidget
, RenderObjectWidget
and so on. But most of the time, we mainly use StatelessWidget
and StatefulWidgets.
Then, where does an InheritedWidget
sit?đ¤
To understand the need for an InheritedWidget, letâs look at the example of this Widget Tree:
Now letâs go through it:
- We want to access the
userName
property in theCustomText
Widget. But to access this property, weâve to pass theuserName
property inside every Widgetâs constructor đď¸ - Here, you can see we had to pass
userName
from just 3 widgets to get insideCustomText
. But for that, we had to write a lot of boilerplate code. Not to forget that we also created a dependency on every widget which is not a good practice.
Thus, we needed a more robustđŞ solution than just passing the data in every Widgetâs constructor đď¸
As you guessed, InheritedWidget
is the solution to this problem. đ But how does anInheritedWidget
helps us to solve this problem? To answer this, let me show you the following graphđ to understand it properly.
As you can see, you can put InheritedWidget
at the top level and directly reach to that widget whenever you want to access the data. Pretty cool, isnât it?đ
Now letâs see how you can implement this in code.
Implementation of an Inherited Widget
- To create an
InheritedWidget
, you have to extend your class withInheritedWidget
- Then youâve to implement 1 method override:
updateShouldNotify
Letâs learn this by an example:
Here, weâve got a few new things to talk about:
- Weâre taking the child Widget from the constructor
updateShouldNotify
: This method is called whenever the data insideInheritedWidget
changes. If this method returns true, it means that the child widgets who are depending on thisInheritedWidget
will be rebuilt. In this method, weâre getting the old InheritedWidget, so that we can verify if the data insideInheritedWidget
has been changed or not. Sounds too complex? Donât worry because weâre gonna talk about it later in-depth đstatic UserDataInheritedWidget? of(BuildContext context)
: Whenever you want to get the data from theInheritedWidget
, you can call this method to get the data inside thisInheritedWidget
.
Fun Fact: Both BLoC and Provider package uses InheritedWidgets behind the scenes đŽ
Now you know that you were using InheritedWidget
since the beginning because whenever you write Theme.of(context)
or MediaQuery.of(context)
, you were actually getting the data from the respectiveInheritedWidget
Now letâs see how you can get the data from the childđś widget.
To get the reference of the InheritedWidget
, you can write this sentence in either build
method in case of a StatelessWidget
or in didChangeDependencies
method in case of StatefulWidget
like this:
Now that you know how you can use InheritedWidget
, letâs take a more deep dive into the mechanismđ¤ of it.
Inherited Widget In-depth
Consider this line: UserDataInheritedWidget.of(context)?.userName
- In this line, weâre getting the reference of the
UserDataInheritedWidget
which is placed on the top of the Widget tree. - Thus, whenever you write .of(context), it registers your widget(In our case
DemoWidget
) as a listenerđ for theUserDataInheritedWidget
- Therefore, whenever the value inside
UserDataInheritedWidget
changes, the widgets that are dependent on it get rebuilt. We will see an example of this in the end.
Some rules to follow while accessing the data from an InheritedWidget
:
- You should avoid calling
.of(context)
method inside theinitState
of aStatefulWidget
because it will not rebuild your Widget when the configuration of anInheritedWidget
changes â - You can call
.of(context)
method inside thebuild
,didChangeDependencies
or indidUpdateWidget
â
Hereâs an example of where you can call the .of(context)
method:
Ok, we can call .of(context)
method inside these lifecycle methods, but how does it work? đ¤
To answer this, letâs first understand which dependency we are talking about in didChangeDependencies
đ¤đ
The answer is these dependencies are created by the dependOnInheritWidgetOfExactType
function. This function was implemented when we were creating an InheritedWidgetâs static of(BuildContext context)
method.
Hence, whenever the datađ˝ inside an InheritedWidget
changes, it will call the didChangeDependencies
method.
You can also call .of(context)
inside build methods as well since the performance difference wonât be that much significant, but since weâve so many widgets in a bigger app, itâs good to use this method inside didChangeDependencies
Fun Fact: Provider calls
getElementForInheritedWidgetOfExactType
method when you set the listen property to false inProvider.of<AppState>(context, listen: false);
so that widgets donât get rebuild when the data insideInheritedWidget
changes.
Now that you know about InheritedWidgets in-depth, letâs see how we can change the configuration of an InheritedWidget so that the widgets that are depending on it get rebuilt.
Demo:
- First, letâs create a
ColorWidget
that extends theInheritedWidget
:
- Here, we are passing
color
along withonColorChanged
method inside the constructor of this Widget. - In the
updateShouldNotify
, weâre checking if the color has been changed or not. And if itâs changed, then weâre returning true so that the widgets that are depending on thisInheritedWidget
gets rebuilt.
Now, letâs see the code for the StatefulWidget
that inserts this InheritedWidget
into the widget tree:
- In this
StatefulWidget
, we are inserting theColorWidget
which is anInheritedWidget
, weâre also setting thecolor
đ¨ variable to green đ˘ color when we press on the ElevetedButton. color
variable of the state object is passed inside theInheritedWidget
Now, letâs see the code for ColorCardWidget
which is inside the Column
:
Here, you can see that in this StatelessWidget
, we are getting the colorđ¨ from the InheritedWidget
. Therefore, whenever the value of color changes, The ColorCardWidget
will get rebuilt.
Now, if you run the code, you should see an output like this:
Therefore, we can confirm that by writing .of(context)
method, it will register that widget as a listener to that InheritedWidget
so that it can rebuild itself whenever the data inside the InheritedWidget
changes.
If you want to try these examples on your own then you can check out my GitHub repository:
I hope I was able to give you some insights on Inherited Widgets by this article. If you didnât understand any of this part or have any doubts, then you can ask me in the comments, or on my LinkedIn and Twitter.
Keep clapping đ (you can appreciate it by clapping 50 times)
We are building a community for developers where anyone can share their ideas or content, ask doubts about Flutter/other tech, collaborate with each other and become a better developer. So if you are interested in being part of this community then you can join our discord server by this link: https://7span.in/club