标签:配置 nts 不可 单位 dynamic 通过 set extend end
Widget 是空间实现的基本逻辑单位,里面存储的是有关视图渲染的配置信息,包括布局、渲染属性、事件响应信息等。
页面渲染遵循“Simple is best”(简单是最好的)理念。Flutter 将 Widget 设计成不可变的,所以当视图渲染的配置信息发生变化时,Flutter 会选择重建 Widget 树的方式进行数据更新,以数据驱动 UI 构建的方式简单高效。
缺点是,因为涉及到大量对象的销毁和重建,所以会对垃圾回收造成压力。但是,Widget 本身并不涉及实际渲染位图,所以它只是一份轻量级的数据结构,重建成本很低。
另外,由于 Widget 的不可变行,可以以较低成本进行渲染节点复用,因此在一个真实的渲染树中可能存在不同的 Widget 对应同一个渲染节点的情况,这无疑又降低了重建 UI 的成本。
Flutter 渲染过程,可以分三步:
Element 同时持有 Widget 和 RenderObject,无论是 Widget 还是 Element,其实都不负责最后的渲染,只负责发号施令,真正干活儿的只有 RenderObject。
因为 Widget 具有不可变性,但 Element 却是不可变的。实际上,Element 树这一层将 Widget 树的变化(类似 React 虚拟 DOM diff)做了抽象,可以只将真正需要修改的部分同步到真实的 RenderObject 树中,最大程度降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个渲染视图树重建。
渲染对象树在 Flutter 的展示过程分为四个阶段,即布局、绘制、合成和渲染。其中,布局和绘制在 RenderObject 中完成,Flutter 采用深度优先机制遍历渲染对象树,确定树中各个对象的位置和尺寸,并把它们绘制到不同的图层上。绘制完毕后,合成和渲染的工作则交给 Skia 搞定。
在 Flutter 中,布局和绘制工作实际上是在 Widget 的另一个子类 RenderObjectWidget 内完成的。RenderObjectWidget 源码如下:
abstract class RenderObjectWidget extends Widget {
@override
RenderObjectElement createElement();
@protected
RenderObject createRenderObject(BuildContext context);
@protected
void updateRenderObjct(BuildContext context, covariant RenderObject renderObjct);
...
}
对于 Element 的创建,Flutter 会在遍历 Widget 树时,调用 createElement 去同步 Widget 自身配置,从而生成对应节点的 Element 对象。而对于 RenderObject 的创建与更新,其实是在 RenderObjectElement 类中完成。
abstract class RenderObjectElement extends Element {
RenderObject _renderObject;
@override
void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot);
_renderObject = widget.createRenderObject(this);
attachRenderObject(newSlot);
_dirty = false;
}
@override
void update(covariant RenderObjectWidget newWidget) {
super.update(newWidget);
widget.updateRenderObject(this, renderObject);
_dirty = false;
}
...
}
如果 Widget 的配置数据发生了改变,那么持有该 Widget 的 Element 节点会被标记为 dirty。在下一个周期的绘制时,Flutter 就会触发 Element 树的更新,并使用最新的 Widget 数据更新自身以及关联的 RenderObject 对象,接下来便会进入 Layout 和 Paint 的流程。而真正的绘制和布局过程,则完全交由 RenderObject 完成:
abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget {
...
void layout(Constraints constraints, {bool parentUsesSize = false}){...}
void paint(PaintingContext context, Offset offset){}
}
标签:配置 nts 不可 单位 dynamic 通过 set extend end
原文地址:https://www.cnblogs.com/shsuper/p/11582698.html