On my way to master flutter widgets are key. In Flutter everything is a widget. And so it's crucial to understand how they work and how Flutter renders Widgets. It's a bit of theory but it will help you to better understand Flutter and write better, more efficient apps.
3 trees to rule them all
The number 3 is magic. And especially in Flutter. Flutter uses 3 so-called trees. Imagine it like an ordinary tree in the forest with a treetop and leafs.
The 3 trees
For every widget, you will have 3 objects. One in each tree.
The first tree is called the Widget tree. This is used to configure the User Interface. There you can configure the properties of the widget and decide how it should look.
The second tree is called the Element tree. This is used to manage and update everything. And with everything, I mean the trees and all references. In the element tree are elements and an element is a specific instance of a widget. This may sound familiar to you if you know OOP (Object Oriented Programming) where you have classes and objects where objects are just instances of a class.
The last missing piece is Render Object. Inside of the Render tree are render objects and this is basically what you are seeing on the screen. You don't see widgets. You see render objects. Render objects will take care of the size, layout, and the actual painting to the screen.
How flutter renders widgets - The 3 states
There it is again. The number 3! Flutter goes through 3 stages when rendering the widgets to the screen. Well, as we learned it's not the widgets we see on the screen. That's are the render objects. But how Flutter approaches this?
1. State: Configure
As I mentioned above the widget tree holds the widgets and in this state, it's all about the configuration of our widgets. Via an API you assign properties and values to your widgets which gets hold by the widget tree.
2. State: Life Cycle
Here the whole life cycle of the UI gets managed. Also here it determines the components that are existing in your UI hierarchy. You can imagine this state as the glue between state 1 and 3.
3. State: Paint
Here the Render tree comes into play. All relevant things about painting will be done here. It takes care of constraints, how the childrens of widgets will actually look like, how big they should be. This is where the render objects get painted on the screen.
Okay, but why 3 trees?
You may ask yourself by now "okay but why? Why Flutter not just use widgets and just one tree?". Actually a very good question.
Its about performance
Ok, first things first.
Widgets are immutable
You cant change widgets. And this is basically why one widget tree is not enough. Just imagine you change for example a text widget. You would need a completely new widget because you can't change the exact same widget. And if you are working with Flutter you may know how often the UI can change.
This means when a widget needs a change the widget object inside the widget tree gets replaced completely and cant be updated.
And here the other 2 trees come into play. Both the Element and the Render Tree getting updated whenever possible instead of created entirely new. And this is a massive performance boost!
Update or not to update?
And how Flutter decides if the Element and Render Object can be updated? Let's imagine you have a Text Widget where you just change the text. The second you change it the CanUpdate Method of the Widget will check two things and if one of them is true the Render Object and Element Object gets updated instead of created entirely new objects.
- Is the runtimeType (the widget type like Text, Column, Container, etc.) still the same?
- Is the key the same?
In our example, the runtimeType is still Text and so it's true and the Element Object will call the updateRenderObject Method that will make sure Render Object gets updated instead of re-created.
The key is a property that you can give to almost every widget and helps Flutter identify a widget. Pretty useful especially for this purpose.
And you can test this behavior quite easily. When you run a Flutter App inside your IDE and open the Flutter DevTools you will have this view:
Here I selected a text widget and inside the red box, you see the Render Object. And this Render Object has an ID that starts with a # symbol. When you change the text for this Text Widget the ID will NOT change. Feel free to try it out!
Summary in 1 sentence
Flutter will try to re-use as many resources (objects in the trees) as possible while trying to create new objects as little as possible.
There are 2 resources I used to learn about this topic and were super helpful to understand it. For the ones of you who are more into videos than pure text, I can highly recommend this of the official Flutter Youtube Channel:
And here are some text with deep dive into the matter in the official Flutter Docs (Flutter has the best documentation I have ever seen, you can basically learn everything from there):
That's it. Pretty cool and clever how Flutter renders widgets if you ask me! If you want to dive even deeper into the topic I can highly recommend the documentation link I posted above. I hope you enjoyed the read and learned something new that you can use to write even better Flutter apps!
Stay connected to me and my content on Twitter.
I love to improve myself every single day even if it's just a tiny bit!
Stay safe and healthy guys!
And as always: develop yourself!