Widget 每次setState 都会重新构建,总是在变化,是不稳定的。渲染并不是渲染的Widget树
Render 树 放的是是RenderObject,并不是所有的Widget都会变成RenderObject
例如:StatefulWidget 是继承Widget 的,但是并不会进入到RenderObject
Row 继承自flex flex 里面有两个声明方法并没有实现,在子类中实现用的
Row 继承子Flex
class Row extends Flex {
/// Creates a horizontal array of children.
///
/// The [direction], [mainAxisAlignment], [mainAxisSize],
/// [crossAxisAlignment], and [verticalDirection] arguments must not be null.
/// If [crossAxisAlignment] is [CrossAxisAlignment.baseline], then
/// [textBaseline] must not be null.
///
/// The [textDirection] argument defaults to the ambient [Directionality], if
/// any. If there is no ambient directionality, and a text direction is going
/// to be necessary to determine the layout order (which is always the case
/// unless the row has no children or only one child) or to disambiguate
/// `start` or `end` values for the [mainAxisAlignment], the [textDirection]
/// must not be null.
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List children = const [],
}) : super(
children: children,
key: key,
direction: Axis.horizontal,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
);
}
Flex 继承自 MultiChildRenderObjectWidget
class Flex extends MultiChildRenderObjectWidget {
MultiChildRenderObjectWidget 继承自 RenderObjectWidget
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget
RenderObjectWidget 继承自 Widget
abstract class RenderObjectWidget extends Widget
他里面有两个声明方法,没有进行实现。在子类进行了
@override
RenderObjectElement createElement();
@protected
RenderObject createRenderObject(BuildContext context);
在 Flex 里面
class Flex extends MultiChildRenderObjectWidget {
实现了 createRenderObject 返回一个 RenderFlex
@override
RenderFlex createRenderObject(BuildContext context) {
return RenderFlex(
direction: direction,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: getEffectiveTextDirection(context),
verticalDirection: verticalDirection,
textBaseline: textBaseline,
);
}
RenderFlex 继承自 RenderBox
class RenderFlex extends RenderBox …
Row 实现了createRenderObject 方法,返回一个RenderFlex 对象
RenderBox 又继承与
并不是所有的Widget都会进行独立渲染
RenderBox 继承自 RenderObject
abstract class RenderBox extends RenderObject
所以我们知道Row 实际上是实例化了一个 RenderObject 加入到Render树中
由上可知并不是所有的widget 都会进行独立渲染,只有继承与 RenderObjectWidget 的才会创建 RenderObject 加入到Render 树中进行独立渲染
Render 树是用来渲染的,里面只有Widget变化的内容
Flutter 中有三棵树
Widget树、Element树、Render树
每个Widget 都会创建一个Elemnent对象
当Element被被创建之后就会去调用mount 方法
通过注释可以知道,当我们的element 加入到树里面之后,framework Flutter引擎就会去调用mount
也就是说一旦 createElement() 走完之后,就会去执行 mount
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
RenderObjectElement createElement();
RenderObjectElement
abstract class RenderObjectElement extends Element
MultiChildRenderObjectWidget
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
@override
MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
}
Flutter 引擎位置
MultiChildRenderObjectElement 将this 传了进去
class MultiChildRenderObjectElement extends RenderObjectElement {
abstract class StatelessWidget extends Widget {
/// Initializes [key] for subclasses.
const StatelessWidget({ Key key }) : super(key: key);
/// Creates a [StatelessElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
@override
StatelessElement createElement() => StatelessElement(this);
class StatelessElement extends ComponentElement
abstract class StatefulWidget extends Widget {
/// Initializes [key] for subclasses.
const StatefulWidget({ Key key }) : super(key: key);
/// Creates a [StatefulElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
@override
StatefulElement createElement() => StatefulElement(this);
class StatefulElement extends ComponentElement
StatelessWidget StatefulWidget 的 element 都继承与 ComponentElement
而且发现RenderObjectWidget 、StatelessWidget 、StatefulWidget 都调用了 createElement(),这是一个隐式调用,看不到源码。
当Element被被创建之后就会去调用mount 方法
通过注释可以知道,当我们的element 加入到树里面之后,framework Flutter引擎就会去调用mount
也就是说一旦 createElement() 走完之后,就会去执行 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.
@mustCallSuper
void mount(Element parent, dynamic newSlot) {
隐式调用 createElement 方法。Element 加入Element 树中
它会创建三种Element
RenderObjectElement 比较特殊,他是独立的。他会调用自己的mount 方法。
@override
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
assert(() {
_debugDoingBuild = true;
return true;
}());
_renderObject = widget.createRenderObject(this);
RenderElement 主要是创建RenderObject 对象
基础 RenderObjectWidget 的Widget 会创建RenderElement
创建RenderElement
Flutter 会调用mount 方法,调用createRanderObject 方法
StatefulElement 继承 ComponentElement
StatefuleWidget会创建StatefulElement
调用createState 方法,创建State
将Widget 赋值给state
调用state的build方法并将其
小结:整个流程:
1、Widget 创建
2、Element createElement
3、mount
4、Render createRenderObject 把this(是当前的 Element) 传进去
看一下StatelessElement
abstract class ComponentElement extends Element {
…
@override
void mount(Element parent, dynamic newSlot) {
…
_firstBuild();
…
}
_firstBuild 里面调用rebuild()
void rebuild() {
…
/// Called by rebuild() after the appropriate checks have been made.
@protected
void performRebuild();
}
performRebuild(); 跟不进去了。选中 command + option + B
@override
void performRebuild() {
…
Widget built;
try {
…
built = build();
build(); 又跟不进去了,同上 选中 command + option + B。记住我们现在跟的是 StatelessElement
跟进去,这时候就可以看到调用了我们的build。 this 是Element
Widget build() => widget.build(this);
这个时候猜测widget 就是我们外面的widget。
这样的话就是在 StatelessWidget 构造的时候,创建了Element 然后调用了mount 方法,然后经过一系列操作之后,调用了build 方法并返回给我吗Element,也就是 StatelessWidget中的 Widget build(BuildContext context) 。
现在证明一下这个widget 是不是外面这个widget
回到
abstract class StatelessWidget extends Widget {
@override
StatelessElement createElement() => StatelessElement(this);
这里给StatelessElement 传的就是我们的Widget,继续跟下去看看
class StatelessElement extends ComponentElement {
StatelessElement(StatelessWidget widget) : super(widget);
super(widget); 还是之前的那个Widget,继续
abstract class ComponentElement extends Element {
ComponentElement(Widget widget) : super(widget);
继续,在Element里面将Widget 赋值给了,变量 _Widget
abstract class Element extends DiagnosticableTree implements BuildContext {
Element(Widget widget)
: assert(widget != null),
_widget = widget;
@override
StatelessWidget get widget => super.widget as StatelessWidget;
调用的确实是外面的widget,这时候我们的widget树就创建出来了,于此同时Element树也就创建完成了
同时Element 里面有个属性 _Widget 指向了 Widget
同时Widget 里面的方法回调的 context 就是对应的Element
与StatelessWidget 也就前面不一样,后面都是继承 ComponentElement 就一样了
abstract class StatefulWidget extends Widget {
@override
StatefulElement createElement() => StatefulElement(this);
class StatefulElement extends ComponentElement {
StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
super(widget) {
…
_state._widget = widget;
这个地方调用的 createState(), 就是 StatefulWidget 中的 createState()。这个时候就创建了State对象
class Test3 extends StatefulWidget {
@override
_Test3State createState() => _Test3State();
}
于此同时,创建的 State 被保存在了Element 的_state属性中
同时还将Widget 赋值给了_state._widget ,这样是为什么我们就可以在State里面通过Widget. 来访问Widget里面的内容了。
并不是多有的widget 都会独立渲染!只有继承RenderObjectWidget 的才会创建RenderObject 对象
在Flutter渲染的流程中,有三课重要的树!Flutter 引擎是针对Render树进行渲染
Widget 树、Element 树、Render 树
每一个Widget 都会创建一个Element 对象
隐式调用 createElement 方法。Element 加入Element 树中
他会创建是那种Element
1、RenderElement
主要创建RenderObject对象
继承RenderElement
Flutter 会调用mount 方法,调用createRanderObject 方法
2、StatefulElement 继承 ComponentElement
StatefulWidget 会创建 StateFulElement
调用createState 方法,创建 State
将Widget 赋值给State
调用 state 的build 方法并且将自己(Element)传出去
build 里面的 context 就是Widget 的 Element!
3、StatelessElement 继承 ComponentElement
StatelessWidget 会创建 StatelessElement
主要就是调用build 方法并且将自己(Element)传出去