Widget到底是什么?Widget是Flutter功能的抽象描述,是视图的配置信息,同样也是数据的映射。是Flutter开发框架中最基本的概念,前端框架中常见的名词,比如视图(View)、视图控制器(View controller)、活动(Activity)、应用(Application)、布局(Layout)等、在Flutter中都是Widget。

Flutter的核心设计思想便是:“一切皆是Widget”

Widget渲染过程

在进行App开发时,我们往往会关注的一个问题时:如何结构化的组织视图数据。提供给渲染引擎,最终完成界面显示。不同UI框架中会以不同的方式去处理这个问题。但无一例外的都会用到视图树(View Tree)。而Flutter将视图树的概念进行了扩展。把视图数据的组织和渲染抽象分为三部分。即Widget、Element和RenderObject。三部分之间的关系如下图:
image.png

Widget

  • Widget是Flutter世界里对视图的一种结构化描述。可以把它看做前端中的控件或者组件。
  • Widget是控件实现的基本逻辑单位,里面存储的是有关视图渲染的配置信息。包括布局、渲染属性、事件响应信息等、
  • 在页面渲染上,Flutter将Widget设计成不可变的所以当视图渲染的配置信息发生变化时,Flutter会选择重建Widget树的方式进行数据更新,以数据驱动UI构建的方式简单有效。
  • Widget本身并不涉及实际渲染位图。所以它只是一份轻量的数据结构。重构成本很低
  • 由于Widget的不可变性,可以以较低成本进行渲染节点复用。因此在一个真实的渲染树中可能存在不同的Widget对应同一个渲染节点的情况。无疑又降低了重构UI的成本

    Element

  • Element 是 Widget 的一个实例化对象,它承载了视图构建的上下文数据,是连接结构化的配置信息到完成最终渲染的桥梁。

  • 渲染过程分三步:
  • 首先、通过Widget树生成对应的Element树。
  • 然后、创建相应的RenderObject 并关联到Element.renderObject属性上。
  • 最后、构建成RenderObject树。已完成最终的渲染。
  • Element同时持有Widget和RenderObject,而无论是Widget还是Element。其实都不负责最后的渲染。只负责发号施令。真正去干活的只有RenderObject。那么,既然都是发号施令,那为什么需要增加中间这层Element树呢?直接由Widget命令RenderObject去干活不好么?
  • 可以、但是会极大地增加渲染带来的性能损耗、
  • 因Widget具有不可变性,但Element却是可变的。实际上、Element树这一层将Widget树的变化做了抽象。

    RenderObject

  • RenderObject是主要负责实现视图渲染的对象、

  • Flutter 通过控件树(Widget树)中的每个控件(Widget)创建不同类型的渲染对象。组成渲染对象树。
  • 渲染对象树在Flutter的展示过程中分为四个阶段、即布局、绘制、合成和渲染、其中、布局和绘制在RenderObject中完成。Flutter采用深度优先机制遍历渲染对象树。确定树中各个对象的位置和尺寸。并把他们绘制到不同的图层上。绘制完毕后,合成和渲染的工作则交给SKia搞定。
  • Flutter 通过引入Widget、Element与RenderObject这三个概念。把原本从视图数据到视图渲染的复杂构建过程拆分的更简单、直接、在易于集中治理的同时,保证了较高的渲染效率。

    RenderObjectWidget

  • StatelessWidget 和 StatefulWidget 只是用来组装控件的容器。并不负责组件最后的布局和绘制。在Flutter中,布局和绘制工作实际上是在Widget的另一个子类RenderObjectWidget内完成的。 ``` abstract class RenderObjetWidget extends Widget { @override RenderObjectElement createElement(); @protected RenderObject createRenderObject(BuildContext context); @protected void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { ….. } }

RenderObjectWidget是一个抽象类,我们通过源码可以看到,这个类中同时拥有创建Element、RenderObject、以 及更新RenderObject的方法

RenderObjectWidget本身并不负责这些对象的创建和更新 ```