Flutter 三棵树

1,140 阅读2分钟

图片.png

查看抽象类实现快捷键: command+option+b

Flutter 渲染原理分析,针对Widget、Element、renderObject进行分析。并详细阐述三者关系

  1. 自己写Widget
  2. 部分Widget会生成RederObject进行渲染
  3. 每一个Widget都会生成对应的Element,每次挂载到树上,都会生成一个Element

4.1 ComponElement会调用mount方法, mout -> firstBuild -> rebuild -> performBuild -> build -> _widget.build

4.2 RenderObjectElement: mount -> widger.createRenderObject

4.3 StatefulElement: 构造方法中 widger.createState()

Widget 到 RenderObject过程

截屏2022-09-26 10.20.55.png

创建过程是要实现RenderObjectWidget内部的createRenderObject方法.具体在Padding来看,是在Padding内部进行了实现

class Padding extends SingleChildRenderObjectWidget {
    @override
    RenderPadding createRenderObject(BuildContext context) {
      return RenderPadding(
        padding: padding,
        textDirection: Directionality.maybeOf(context),
      );
    }
}

RenderPadding --> RenderShiftedBox --> RenderBox --> RenderObject

具体调用地方待查看?

Widget 到 Element 的过程

截屏2022-09-26 10.30.10.png

可以看出抽象方法是在Widget里面定义的,是所有抽象方法的根,也就是说无论是渲染Widget非渲染Widget(所有Widget)都要实现这个方法. 创建一个Element

非渲染Widget渲染Widget
StlessElementRenderElement
StatefulElement
mount方法

调用顺序:mount -> firstBuild -> rebuild -> performBuild -> build -> _widget.build

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. 

@mustCallSuper
void mount(Element? parent, Object? newSlot) {
}

ComponentElement中 (stless、stful都是继承ComponentElement)

/// **********Class ComponentElement
@override
void mount(Element? parent, Object? newSlot) {
  super.mount(parent, newSlot);
  _firstBuild();
}


void _firstBuild() {
  // StatefulElement overrides this to also call state.didChangeDependencies.
  rebuild(); // This eventually calls performRebuild.
}


/// **********Class Element
void rebuild() {
    performRebuild();
}
// 抽象方法,查看具体(command+option+b)实现在ComponentElement中
void performRebuild();

/// **********Class ComponentElement
void performRebuild() {
    built = build();
}

// 抽象方法
@protected
Widget build();

/// ***********Class StlessElement
// widget是创建Element时候,传入的
Widget build() => (widget as StatelessWidget).build(this);

RenderObjectElement

void mount(Element? parent, Object? newSlot) {
  _renderObject = (widget as RenderObjectWidget).createRenderObject(this);
}

StatefulElement

StatefulElement(StatefulWidget widget): _state = widget.createState(), 
    super(widget) { 
    // 将widget进行了赋值操作
    state._widget = widget;    
}

// stful这里的build,可以看出是调用state的build方法,同时将Element传出去
@override
Widget build() => state.build(this);

可以看出,Element内部,既有Widget也包含RenderObject,还包含state

// StlessElement
Widget build() => (widget as StatelessWidget).build(this);


// RenderObjectElement
_renderObject = (widget as RenderObjectWidget).createRenderObject(this);


// StatefulElement
StatefulElement(StatefulWidget widget): _state = widget.createState(), 
    super(widget) { 
}

总结:StlessWidget 调用 CreateElement方法,创建ELement, Element调用mount方法,mount方法内部调用Widget的build方法

参考:Flutter的Widget-Element-RenderObject