主要是通过底层源码来分享一下Flutter是怎么渲染的。
1、Widget树
树是一种数据结构,Widget树就是存储Widget的树结构。Widget的功能是“描述一个UI元素的配置数据”,它就是说,Widget其实并不是表示最终绘制在设备屏幕上的显示元素,而它只是描述显示元素的一个配置数据。下面就是Flutter官方Demo的Widget树展示:

经常需要根据不同的数据来展示不同的
UI就导致了Widget树极其不稳定,所以Flutter的引擎在渲染的时候不是直接来渲染Widget树,而是渲染Rander树。Rander树展示:
2、Rander树
上面说到了Flutter引擎是直接渲染Rander树的,Rander树里面存的是RanderObject。但不是所有的Widget都会变成独立RanderObject,只有继承RenderObjectWidget的Widget才会生成独立RanderObject并且加到Rander树里面,进行独立渲染。RenderObjectWidget的定义如下:
/// RenderObjectWidgets provide the configuration for [RenderObjectElement]s,
/// which wrap [RenderObject]s, which provide the actual rendering of the
/// application.
abstract class RenderObjectWidget extends Widget {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const RenderObjectWidget({ Key? key }) : super(key: key);
/// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
@override
@factory
RenderObjectElement createElement();
/// Creates an instance of the [RenderObject] class that this
/// [RenderObjectWidget] represents, using the configuration described by this
/// [RenderObjectWidget].
///
/// This method should not do anything with the children of the render object.
/// That should instead be handled by the method that overrides
/// [RenderObjectElement.mount] in the object rendered by this object's
/// [createElement] method. See, for example,
/// [SingleChildRenderObjectElement.mount].
@protected
@factory
RenderObject createRenderObject(BuildContext context);
/// Copies the configuration described by this [RenderObjectWidget] to the
/// given [RenderObject], which will be of the same type as returned by this
/// object's [createRenderObject].
///
/// This method should not do anything to update the children of the render
/// object. That should instead be handled by the method that overrides
/// [RenderObjectElement.update] in the object rendered by this object's
/// [createElement] method. See, for example,
/// [SingleChildRenderObjectElement.update].
@protected
void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
/// A render object previously associated with this widget has been removed
/// from the tree. The given [RenderObject] will be of the same type as
/// returned by this object's [createRenderObject].
@protected
void didUnmountRenderObject(covariant RenderObject renderObject) { }
}
/// A superclass for RenderObjectWidgets that configure RenderObject subclasses
/// that have no children.
abstract class LeafRenderObjectWidget extends RenderObjectWidget {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const LeafRenderObjectWidget({ Key? key }) : super(key: key);
@override
LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
}
RenderObjectWidget是Widget的子类,这里面我们需要关注两个方法:RenderObjectElement createElement()和RenderObject createRenderObject(BuildContext context),这两个都是抽象方法,需要子类去实现的。
要看createRenderObject,首先找到哪些Widget是继承RenderObjectWidget,比较常见的有Flow、Flex、Column、Row等。Row来说看一下其继承关系:
class Row extends Flex{...}
class Flex extends MultiChildRenderObjectWidget {...}
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {...}
Row是继承Flex的,在Row定义里面没有看到createRenderObject的实现,那去Flex里面去找:

可以找到,在Flex里面把这个方法实现了,所以继承Flex的Widget都实现了这个方法。返回一个RenderFlex对象,看一下它的继承关系:
class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData>,
DebugOverflowIndicatorMixin{...}
abstract class RenderBox extends RenderObject {...}
3、Elment树
Element就是Widget在UI树具体位置的一个实例化对象,每生成一个Widget都会对应生成一个Element,看看是不是这样的。
先看Widget的定义:
abstract class Widget extends DiagnosticableTree {
...
/// Inflates this configuration to a concrete instance.
///
/// A given widget can be included in the tree zero or more times. In particular
/// a given widget can be placed in the tree multiple times. Each time a widget
/// is placed in the tree, it is inflated into an [Element], which means a
/// widget that is incorporated into the tree multiple times will be inflated
/// multiple times.
@protected
@factory
Element createElement();
...
}
Widget里面定义了一个Element createElement()方法,来看看子类都是怎么实现的。
- 首先是上面提到的
RenderObjectWidget的一个子类MultiChildRenderObjectWidget:
@override
MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
它返回的是MultiChildRenderObjectElement这个类型:
class MultiChildRenderObjectElement extends RenderObjectElement {...}
abstract class RenderObjectElement extends Element {...}
从继承关系来看,它也是继承Element的。
- 然后再看看
StatelessWidget,它是继承Widget的:
@override
StatelessElement createElement() => StatelessElement(this);
它返回一个StatelessElement类型:
class StatelessElement extends ComponentElement {...}
abstract class ComponentElement extends Element {...}
从继承关系来看,它也是继承Element的。
- 最后看看
StatefulWidget,它也是是继承Widget的:
@override
StatefulElement createElement() => StatefulElement(this);
它返回一个StatefulElement类型:
class StatefulElement extends ComponentElement {...}
abstract class ComponentElement extends Element {...}
从继承关系来看,它也是继承Element的。
从上面的分析来看,确实每一个Widget都实现了createElement(),那是什么时候调的呢?它的调用是Flutter隐试调的,肯定会调的,可以在debug模式打个断点看看。
所以说每一个Widget都会有一个Element与之对应,最后会根据Widget树创建一个Element树。
-
总结一下,我们可以认为Flutter的UI系统包含三棵树:Widget树、Element树、渲染树。他们的依赖关系是:Element树根据Widget树生成,而渲染树又依赖于Element树,如图所示:
image.png
4 、mount函数
Widget创建的时候就会创建Element对象然后加入到Element树里面,在第一次加入Element树的时候,就会触发Flutter引擎调一个Element方法——mount(),看一下这个方法的定义:
...
/// Add this element to the tree in the given slot of the given parent.
///
/// The framework calls this function when a newly created element is added to
/// the tree for the first time. Use this method to initialize state that
/// depends on having a parent. State that is independent of the parent can
/// more easily be initialized in the constructor.
///
/// This method transitions the element from the "initial" lifecycle state to
/// the "active" lifecycle state.
///
/// Subclasses that override this method are likely to want to also override
/// [update], [visitChildren], [RenderObjectElement.insertRenderObjectChild],
/// [RenderObjectElement.moveRenderObjectChild], and
/// [RenderObjectElement.removeRenderObjectChild].
@mustCallSuper
void mount(Element? parent, dynamic newSlot) {
assert(_lifecycleState == _ElementLifecycle.initial);
assert(widget != null);
assert(_parent == null);
assert(parent == null || parent._lifecycleState == _ElementLifecycle.active);
assert(slot == null);
_parent = parent;
_slot = newSlot;
_lifecycleState = _ElementLifecycle.active;
_depth = _parent != null ? _parent!.depth + 1 : 1;
if (parent != null) // Only assign ownership if the parent is non-null
_owner = parent.owner;
final Key? key = widget.key;
if (key is GlobalKey) {
key._register(this);
}
_updateInheritance();
}
...
这个方法非常重要,上面是Element的mount()的实现,来看看他的子类RenderObjectElement、StatelessElement和StatefulElement的mount()方法都做了哪些事情。
4.1、 RenderObjectElement的mount()
...
@override
void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot);
assert(() {
_debugDoingBuild = true;
return true;
}());
_renderObject = widget.createRenderObject(this);
assert(() {
_debugDoingBuild = false;
return true;
}());
assert(() {
_debugUpdateRenderObjectOwner();
return true;
}());
assert(_slot == newSlot);
attachRenderObject(newSlot);
_dirty = false;
}
...
这里面最要的一个方法就是_renderObject = widget.createRenderObject(this);,它说明了RenderObjectElement创建之后Flutter引擎就会创建renderObject,创建完成之后就会调attachRenderObject(newSlot);方法添加到渲染树中。
4.2、 StatelessElement的mount()
在StatelessElement类里面并没有看到mount()方法,在找其父类ComponentElement的mount()方法:
@override
void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot);
assert(_child == null);
assert(_lifecycleState == _ElementLifecycle.active);
_firstBuild();
assert(_child != null);
}
这里面调了_firstBuild();方法:
void _firstBuild() {
rebuild();
}
接着往下走:
/// Called by the [BuildOwner] when [BuildOwner.scheduleBuildFor] has been
/// called to mark this element dirty, by [mount] when the element is first
/// built, and by [update] when the widget has changed.
void rebuild() {
...
performRebuild();
...
}
又调了performRebuild():
@protected
void performRebuild();
到这里就点不进去了,我们可以同时按住command+alt+B,就会搜到实现:

这里选择CompentElement的performRebuild进去就可以看到实现:
/// Calls the [StatelessWidget.build] method of the [StatelessWidget] object
/// (for stateless widgets) or the [State.build] method of the [State] object
/// (for stateful widgets) and then updates the widget tree.
///
/// Called automatically during [mount] to generate the first build, and by
/// [rebuild] when the element needs updating.
@override
void performRebuild() {
...
built = build();
...
}
这里调了一个build()方法:
/// Subclasses should override this function to actually call the appropriate
/// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
/// their widget.
@protected
Widget build();
同样按住command+alt+B,搜实现:

选择StatelessElement的实现:
@override
Widget build() => widget.build(this);
这里调到了widget的bulid()方法,并且将this做为参数传了出去,这里的this指的就是StatelessElement,那这的widget是什么呢,看一下StatelessElement的定义:
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget);
@override
StatelessWidget get widget => super.widget as StatelessWidget;
@override
Widget build() => widget.build(this);
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}
StatelessElement的构造方法提供了一个参数widget,并传递给其父类的父类Element,Element通过构造方法:
Element(Widget widget)
: assert(widget != null),
_widget = widget;
赋值给成员变量_widget,保存起来,并提供一个获取的方法widget来获取_widget:
/// The configuration for this element.
@override
Widget get widget => _widget;
在StatelessElement这个类里面重写了Element的widget方法:
@override
StatelessWidget get widget => super.widget as StatelessWidget;
在StatelessWidget可以看到:
@override
StatelessElement createElement() => StatelessElement(this);
在创建StatelessElement的时候是将this传给了StatelessElement的构造方法,这个this就是StatelessWidget。
根据上面的分析StatelessElement里面的:
@override
Widget build() => widget.build(this);
widget就是StatelessWidget,this指的就是StatelessElement。
来看Flutter官方的Demo:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
这个build方法的参数context其实就是StatelessElement。
4.3、 StatefulElement的mount()
StatefulElement和StatelessElement一样都没有实现mount()方法,都是在他们父类ComponentElement中实现的,流程是一样的,不一样的是build()方法:
@override
Widget build() => state.build(this);
StatefulElement的build方法是调state的bulid方法,这个跟StatelessElement不一样,这个state是哪里来的呢,看一下StatefulElement的构造方法实现:
/// Creates an element that uses the given widget as its configuration.
StatefulElement(StatefulWidget widget)
: state = widget.createState(),
super(widget) {
assert(() {
if (!state._debugTypesAreRight(widget)) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>'),
ErrorDescription(
'The createState function for ${widget.runtimeType} returned a state '
'of type ${state.runtimeType}, which is not a subtype of '
'State<${widget.runtimeType}>, violating the contract for createState.'
),
]);
}
return true;
}());
assert(state._element == null);
state._element = this;
assert(
state._widget == null,
'The createState function for $widget returned an old or invalid state '
'instance: ${state._widget}, which is not null, violating the contract '
'for createState.',
);
state._widget = widget;
assert(state._debugLifecycleState == _StateLifecycle.created);
}
这个方法里面有两个重点:
-
state = widget.createState(),在创建StatefulElement的时候,调widget的createState()方法创建一个State对象保存在成员变量state里面,这就是为什么StatefulWidget实现createState()。 -
state._widget = widget;,将widget保存在state的_widget成员变量中,在state里面提供一个获取_widget的方法——widget:
abstract class State<T extends StatefulWidget> with Diagnosticable {
...
T get widget => _widget!;
T? _widget;
...
}
这就是为什么在State里面可以使用widget的原因。
