The BuildContext classs in Flutter.
By: Greg Perry
Tags: Programming, Flutter, Android App Development, Mobile App Development, iOS App Development

Do you know what that context object is? You know what object I mean, the BuildContext object named, context, that’s passed to the build() function all the time. It’s a necessary parameter to a bunch of static functions as well:

build(BuildContext context)

Theme.of(context)

Scaffold.of(context)

MediaQuery.of(context)

Navigator.of(context)

It helps you go up and or through the ‘render tree’ (or widget tree). In this article, we’ll take a closer look at it. That means, we’re going to look ‘under the hood’ of the Flutter framework and get down to what exactly makes up this BuildContext object named context. That means we’re walking through the code. In fact, let’s not keep you in suspense, I’ll tell you right now what this object is.

It’s an element.

I Like Screenshots. Click For Gists.

As always, I prefer using screenshots in my articles over gists to show concepts rather than just show code. I find them easier to work with frankly. However, you can click or tap on these screenshots to see the code in a gist or in Github. Further, it’s better to read this article about mobile development on your computer than on your phone. Besides, we program mostly on our computers — not on our phones. Not yet anyway.

Let’s begin.

Not In Context

As it happens, We’re not going to examine the BuildContext class itself to any great detail per se. With it seemingly being such a pivotal player in the Flutter framework, simply presenting the part it does play in a typical app should be enough. Besides, it’s an abstract class — you have to create a subclass and implement all the fields and functions it contains.

I’ll present a screenshot of the class below with all its documentation and deprecated functions removed — just to give you a hint as to its role in Flutter. You may recognize some of the functions in contains and may even be surprised that it’s in this class where these functions reside. Next, we’ll determine the precise subclass that uses BuildContext. Granted, I have already spilled the beans on that one, but act surprised anyway, ok?

The Element of Widgets

Let’s step back a bit and first look at the class, StatelessWidget. Below is a screenshot of one with all it’s documentation stripped out as well so you can see just what a StatelessWidget is made up of. Not much to it, is there? It’s an abstract class, and so a subclass must, of course, implement its build() function. We pretty much knew that already. However, what’s this createElement() function? It instantiates another class called, StatelessElement, and actually passes a reference to itself as a parameter. Let’s take a look at that class next.

For the class, StatelessElement, I decided to leave the documentation in — what little there is. Pretty short class as well. Note, it takes the StatelessWidget parameter and passes it on to its own parent class, ComponentElement, and so, we’ll press on there.

The class, ComponentElement, gets a little more involving, and so I just took a screenshot of the start of this class. Note, it too is an abstract class. Makes sense too, as it contains the very build() function that needs to be implemented. Of course, what we’re doing here is going back through the class hierarchy at the moment. Don’t worry, we’ll be re-visiting these ‘intermediary’ classes again. We now have the class, Element, to look at next.

Again, we’re looking at just the start of the class, Element, next. Good thing too. In comparison to the classes so far, this one’s huge. In all, it’s made up of 90 functions and properties. Yeah, this is indeed an important ‘element.’ However, we’ve arrived at what I was getting at. What do you see?

The class, Element, implements the class, BuildContext. Unlike Java, for example, any class in the Dart programming language can be utilized as an Interface — you merely append its name on the end of a class declaration behind the keyword, implements. Of course, unless your class’s abstract, you then have to implement all the functions and fields that make up that class. In the case of the class, Element, implementing the BuildConext class with its many members — no wonder there’s now a large number of functions and fields. With this little exercise finally over, we can conclude, as with all object-oriented languages, an object of type, Element, can also be passed to functions or constructors as an object of type, BuildContext. Surprise!!

The Flutter documentation states they decided to use the BuildContext as an Interface so to discourage direct manipulation of Element objects — whatever that means. I mean, who wants to deal with 90 class properties anyway!?

So, now you know, when you place a breakpoint in your favorite IDE right on the build() function line, you’ll discover the context parameter passed to that function is, in the case of the StatelessWidget, the very StatelessElement object we first saw instantiated back in the StatelessWidget screenshot. Note, the same is true for the StatefuleWidget. In its case, however, it involves the object, StatefulElement. Both these two types of widgets are listed below.