This is the 27th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
1. Rendering principle
The layout and drawing process of the Flutter framework is as follows:
- Generate an Element tree from the Widget tree, and the nodes in the Tree inherit from the Element class.
- The Render tree is generated from the Element tree, and the nodes in the Render tree inherit from the RenderObject class.
- Generate the Layer tree according to the rendering tree, and then display on the screen, the nodes in the Layer tree are inherited from the Layer class.
In the Render tree, Element is the glue between Widget and RenderObject and can be understood as an intermediary agent.
2. The Render tree
Not all widgets generate Render; for example, containers do not create RenderObjects.
RenderObject objects are generated only for objects that inherit from the RenderObject class, such as Column, and are rendered directly by the rendering engine.
The two important methods in renderObject are createElement and createRenderObject. Both of these methods are abstract and should be implemented in subclasses.
Let’s start with the createRenderObject method, whose implementation is found in Flex. The only thing you do in createRenderObject is create RenderFlex
RenderFlex inherits from RenderBox.
The RenderBox inherits from the RenderObject.
So createRenderObject is just returning a RenderObject. That said, not all widgets will be rendered independently. Only widgets that implement createRenderObject and return RenderObject will be rendered independently.
3. The Element tree
All widgets create an Element object. See the createElement method above.
RenderObjectElement createElement();
Copy the code
See how the class implements the createElement method. Here in MultiChildRenderObjectWidget found method implementation, here returned a MultiChildRenderObjectElement object.
MultiChildRenderObjectElement inherited from RenderObjectElement.
Next, see if the StatelessWidget implements the createElement method. I went in and there was.
Take a look at statefulWidgets, too.
As you can see here, all widgets that inherit from widgets have elements. So you can see that the Widget tree corresponds to the Element tree in a one-to-one way.
Run after a breakpoint is set on createElement in the StatefulWidget.
The first thing that calls this method here is the Material app.
If it’s createElement in the StatelessWidget, it should be MyApp.
I go down a step and I get here, and I see a mount method called.
The mount method is called whenever a new element is added. This means that the mount method is called every time a new Widget is created.
Now look at the mount method in the renderObject. The createElement method in MultiChildRenderObjectWidget method lay a breakpoint.
Click next to find that the mount method is also called.
The createRenderObject comes after the mount method, which is createElement. So the process is Widget tree — Element tree — Render tree
The RenderObject is created by calling createRenderObject in the mount function below createRenderObject.
4. The relationship between Element and Widget
StatelessWidget createElement is StatelessElement.
StatelessElement inherits from ComponentElement
I go to ComponentElement, and I see that there’s a mount method, and I call _firstBuild in mount.
_firstBuild calls rebuild.
There’s also a bunch of judgments in rebuild, and then I call the performRebuild method.
See performRebuild is just a definition.
Now go to componentElement and look at the performRebuild method. See the built variable here, and it equals the build method
See that build is also a method definition.
See that the Build method in StatelessElement returns the value of the widget’s build method, which is the StatelessWidget.
So, when you create a StatelessWidget object, it will
- Call the createElement method,
-
- Create the componentElement object and call the mount method
- Call the _firstBuild method
- Calling the rebuild method
- Call the performRebuild method
- Call the build method in StatelessElement
- The Build method of the StatelessWidget object is called to render
This proves that the widget inside the StatelessElement is the external StatelessWidget object. When createElement is called here, this is the StatelessWidget object.
In StatelessElement, the widget is the StatelessWidget object passed in and passed to super.
Goes to ComponentElement, passes super to ComponentElement.
We then see that the widget is received in Element and assign it to _widget.
- How widgets render
- Not all widgets are rendered independently! RenderObjectWidget creates RenderObject objects only if it inherits RenderObjectWidget!
- There are three important trees in the Flutter rendering process! The Flutter engine renders against the Render tree!
- Widget tree, Element tree, Render tree
- Each Widget creates an Element object
- Implicitly call the createElement method. Element is added to the Element tree, which creates three elements
- RenderElement is used to create RenderObject objects. Widgets that inherit from RenderObjectWidget create RenderElement
- Create RanderElement
- Flutter calls the mount method and createRanderObject method
- StatefulElement inherits ComponentElement, and StatefulWidget creates a StatefulElement
- Call the createState method to create the State
- Assign the Widget to state
- Call the state build method and pass itself out. The context inside the build is the Widget’s Element!
- StatelessElement inherit ComponentElement StatelessWidget creates StatelessElement
- Basically, call the build method and pass itself out
- Each Widget creates an Element object
- Widget tree, Element tree, Render tree