主要是通过底层源码来分享一下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树,如图所示:
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
的原因。