BuildContext
is one of the concepts in Flutter that most developers, even seasoned ones, find hard to understand. Many developers don’t actually know what it does or what it stands for. Yet, BuildContext
is an important concept that every Flutter dev should understand deeply.
In this post, we will demystify the mystery around BuildContext
.
Everything in Flutter is a widget. Whether it is a container, text, button, providers, image, etc., everything is virtually a widget, no matter if they display a UI in the app or not.
The UI or display in Flutter comprises stacks of widgets popularly called a widget tree. If you are coming from a JavaScript background or have used either Reactjs or Angular, you will understand this. In Reactjs, the UI is made up of a tree of components. Each component is responsible for a small unit of the entire UI.
In Flutter, it is not a component, rather it is a widget. A widget is responsible for a small unit in a Flutter app. As in
A widget that renders another widget is the parent widget, which renders the the child widget. The MyApp
widget is usually the root widget, just like the App
component is usually the root component in React.
Let’s see an example:
MyApp
|
Container
|
Row
|
----------
| |
Text FlatButton
In the above diagram, we can see a widget tree in a Flutter app. The MyApp
is the root widget, and it is the parent of all the widgets in the tree. The MyApp
widget renders the Container
widget, and the Container
widget renders the Row
widget. The Row
widget renders both Text
and FlatButton
widgets.
So, we can say that MyApp
is the parent of Container
, and that the Container
is the parent of Row
and the child of MyApp
. The Row
is the child of Container
and parent of Text
and FlatButton
. Text
and FlatButton
are the children of Row
.
Now that we can see the relationship, let’s see how BuildContext
comes in.
BuildContext
?BuildContext
is a locator that is used to track each widget in a tree and locate them and their position in the tree.
The BuildContext
of each widget is passed to their build
method. Remember that the build
method returns the widget tree a widget renders.
Each BuildContext
is unique to a widget. This means that the BuildContext
of a widget is not the same as the BuildContext
of the widgets returned by the widget.
MyApp {
build(BuildContext ctx) {
return Container(
child: Row(
children: [
Text(),
FlatButton()
]
)
)
}
}
The BuildContext
in the MyApp
widget is different from the BuildContext
in the Container
widget and all widgets in its tree. So, the BuildContext
of the MyApp
is the BuildContext
parent of the BuildContext
s of its child widgets.
The MyApp
has its BuildContext
, Container has its BuildContext
, Row has its BuildContext
, and Text and FlatButton have their own BuildContext
, all of which are unique to each other.
BuildContext
findAncestorWidgetOfExactType
Returns the nearest ancestor widget of the given type T, which must be the type of a concrete
Widget
subclass.
This method is used to locate or find a widget of a particular type in the widget tree. This method will go up the widget tree from the widget it was called from, and try to locate the first widget in the tree whose type is the same one passed to the method.
Let’s say we have this widget tree: MyApp -> Scaffold -> Center -> Row -> Container -> Row -> Text -> TextButton
. If the method is called from the Text
widget:
context.findAncestorWidgetOfExactType(Row);
The method will traverse up the widget, starting from the Text
widget and stopping when it locates a widget whose type is Row
. So, the first Row
in-between Container
and Text
will be returned.
findAncestorStateOfType
Returns the State object of the nearest ancestor
StatefulWidget
widget, an instance of the given type T.
This method is just like the findAncestorWidgetOfExactType
method, b. Still, this returns the State
object of a StatefulWidget
widget whose instance is the same as the instance passed to the method.
We have seen that BuildContext
is crucial in understanding how Flutter works. Understanding how Flutter works deepens our knowledge of the framework and helps us build apps confidently.