Flutter 的烘托体系中,Framework 层首先会依据页面界说的元素生成一个个由 Layer 组成的Scene目标,接着ui.window会将这些烘托信息传递到 Engine 层,Engine 层调用底层烘托引擎的接口将这些像素信息制作到屏幕上。

导读

对于开发者而言,Framework 层烘托是最直接接触到的,了解其间的原理可辅助咱们定位问题,写出更高效的代码。这个系列文章将会环绕烘托流程做深入解析,分为以下几部分:

  • Flutter Framework 烘托流程剖析(一):开篇
  • Flutter Framework 烘托流程剖析(二):Element
  • Flutter Framework 烘托流程剖析(三):RenderObject
  • Flutter Framework 烘托流程剖析(四):Layer
  • Flutter Framework 烘托流程剖析(五):常见问题剖析

Widget

Flutter Framework 渲染流程分析(一):开篇

Widget 能够分为三类目标。一类是制作类,对应RenderObjectWidget,担任布局和制作,烘托流程中的LayoutPaint阶段就与其严密相关;一类是布局类,对应StatelessWidgetStatefulWidget,它更像是一个组织者,经过组合各种RenderObjectWidget来丰富页面的布局;一类是署理类,对应ProxyWidget,它能向子节点提供额定的数据,方便咱们开发时在 Widget Tree 之间传递数据。

制作类是核心的功能模块,布局类将这些模块进行堆叠,而署理类则是在这些模块之间传递数据。

Widget 的要害办法

// code 1.1
// Note: [] 内是类名,后边是办法名。下同!
[Widget] Element createElement();
[Widget] static bool canUpdate(Widget oldWidget, Widget newWidget) {...};
[StatelessWidget] Widget build(BuildContext context);
[StatefulWidget] State createState();
[State] Widget build(BuildContext context);
[RenderObjectWidget] Renderobject createRenderObject(BuildContext context);

经过这些办法,能够得出:

  1. ElementRenderObject都是从Widget发生的(经过相应的create办法);
  2. 所有 Widget 都对应于一个 Element,但只有RenderObjectWidget 才有对应的 RenderObject
  3. 有两个build办法,一个是StatelessWidget的,别的一个是State的。但间接或直接都归属于布局类,究竟像上面说的只有布局类才会包括子组件并进行组合。

Element

Flutter Framework 渲染流程分析(一):开篇

Element 简化了一下分类。一种是制作类,也就是RenderObjectElement;另一种是组件类,也就是ComponentElement,它囊括了上述Widget中的布局类署理类

Element 的要害特点

// code 1.2
[Element] Widget? _widget;
[Element] RenderObject? renderObject;
[Element] Element? _parent;
[Element] Object? _slot;
[ComponentElement] Element? _child;
[SingleChildRenderObjectElement] Element? _child;
[MultiChildRenderObjectElement] List<Element> _children;

Element持有widgetrenderObject目标,这很重要,咱们常说的三棵树的构成就与其休戚相关。 事实上Element在烘托流程中的build阶段都是至关重要的。一起,它也持有 _parent element_child element,构成一个双向链表数据结构

Element 的要害办法

// code 1.3
// 1. 挂载操作。将自己挂载到树上。
[Element] void mount(Element? parent, Object? newSlot)
// 2. 构建操作。 
[ComponentElement] void _firstBuild()
[Element] void rebuild({bool force = false});
[Element] void performRebuild()
[RenderObjectElement] void _performRebuild()
// 3. 更新元素。执行更新或者从头新建
[Element] Element? updateChild(Element? child, Widget? newWidget, Object? newSlot);
[Element] void update(covariant Widget newWidget)
[Element] Elment inflateWidget(Widget newWidget, Object? newSlot);

Element经过以上这些办法构成一棵树。它在挂载(mount)自身的时分会触发构建(performRebuild)行为,在构建的进程中会经过前面提到的[Widget]build()办法得到child widget,经过 updateChild最终会走到加载(inflateWidget)inflateWidget办法经过child widgetcreateElement办法得到child element,然后child element又会执行mount办法将自己挂载到这棵树上,mount行为便构成一个循环的操作。

AbstractNode

咱们将在第三、四篇介绍的RenderObjectLayer的基类都是AbstractNode,用来表明一棵树上的笼统节点。

// code 1.4
// 1. 深度。节点的深度标志和更新
[AbstractNode] int get depth => _depth;
[AbstractNode] int _depth = 0;
[AbstractNode] void redepthChild(AbstractNode child) {}
[AbstractNode] void redepthChildren() { }
// 2. 持有。节点的持有者,通常情况下所有节点的被同一个 owner 持有。
[AbstractNode] Object? get owner => _owner;
[AbstractNode] Object? _owner;
[AbstractNode] bool get attached => _owner != null;
[AbstractNode] void attach(covariant Object owner) {}
[AbstractNode] void detach() {}
// 3. 父节点。插入节点或移除节点时会对父节点进行更新。
[AbstractNode] AbstractNode? get parent => _parent;
[AbstractNode] AbstractNode? _parent;
[AbstractNode] void adoptChild(covariant AbstractNode child) {}
[AbstractNode] void dropChild(covariant AbstractNode child) {}

依据以上接口,将一个节点笼统出了三个特性:深度持有者父节点。经过_parent,便构成了一个树结构。

为什么Element不承继自AbstractNode?上面咱们说过,Element也是一个树结构,AbstractNode的特性depthownerparentElement都有同名特点存在,但由于Element承继了一个用于记载节点信息的类DiagnosticableTree,而dart做不到多承继。事实上我以为Element理应也承继自AbstractNode,究竟同样身为树结构,只不过需求别的用Mixin处理一下跟DiagnosticableTree的关系即可。

总结

作为开篇引言,本文简略的讲了WidgetElementAbstractNode这几个类,经过类的要害特点和办法介绍了它的作用。关于Element中树的构建,在下个章节中会具体介绍,咱们常说的Widget TreeElement TreeRenderObject Tree其实都是间接经过Element构建进程中构成的。