在flutter开发中,最常用的就是StateflessWidget
和StatefulWidget
了,但是它们只是用来组装控件的容器,那么真正的布局和绘制工作是在哪里完成的呢?
Widget
我们先从一个很简单的组件看起 —— Opacity
,看看flutter源码是如何实现。
1 | class Opacity extends SingleChildRenderObjectWidget { |
通过源码看出Opacity
是继承自SingleChildRenderObjectWidget
,SingleChildRenderObjectWidget
又继承自RenderObjectWidget
最终继承自Widget
。
我们最常使用的StatelessWidget
、StatefulWidget
也继承自Widget
。
它们的不同之处在于,StatelessWidget
、StatefulWidget
只是将其它的Widget组装起来,而Opacity
会影响到Widget
的绘制。但是在上面的源码中我们并没有看到与绘制相关的属性,是因为Widget
只持有控件的配置信息,例如Opacity
只持有属性opacity
。
那么渲染是在哪里发生的呢?
其实从源码的名字可以看出,createRenderObject
创建渲染对象,RenderObject
就是负责渲染工作的。最终创建了一个RenderOpacity
对象。
RenderOpacity
实现布局、点击检测、计算大小等函数。在paint
函数中操作canvas
画布来进行透明度控制。
所以,在flutter中Widget
只是一个配置,RenderObject
来负责布局、绘制等操作。
Element
我们知道了Widget
和RenderObject
。在flutter中,它们并不是直接关联在一起的,而是要通过一个中间人Element
。
1 |
|
在Widget
源码中可以看出,每个Widget都要实现一个createElement
方法来创建Element
对象。
Element
会同时持有Widget
和RenderObject
,在Widget
发生变化时,比较新旧变化,并进行相应的更新。
在Opacity
中,Element
是在SingleChildRenderObjectWidget
中创建
1 |
|
Element
通过mount
方法插入到Element Tree时,同时调用了widget的createRenderObject
方法并保存在变量中。
1 |
|
总结
本文简单描述了Widget
、Element
、RenderObject
之间的关系,由此了解了在flutter中是如何渲染组件的。当然其中的细节还很多,之后的文章会一一解析。