在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中是如何渲染组件的。当然其中的细节还很多,之后的文章会一一解析。