顺着代码看:
入口函数 main
Dart 是从 main
方法开始的,通过 runApp
方法把做为 App 的 Widget 构建出来:
runApp 方法
可以注意到,
runApp
方法会初始化一个 WidgetsFlutterBinding
对象,然后通过 scheduleAttachRootWidget
方法,把 App 小组件安排到了根小组件上。
attachRootWidget 方法
可以发现我们的 App 被当作成 rootWidget,在
attachRootWidget
方法中,通过 RenderObjectToWidgetAdapter
这个 Widget,把 App 作为 child 来构建它,然后执行了它的 attachToRenderTree
方法。由于 renderViewElement 是跟随 WidgetsFlutterBinding
一同被构建的,而 renderViewElement 还没有被实例化,所以传进方法内的值为 null。
attachToRenderTree 方法
element 为 null,则会依次执行
createElement
和 mount
方法。
createElement 方法
createElement
会实例化一个叫做 RenderObjectToWidgetElement
的 Element
,并把自己(RenderObjectToWidgetAdapter
)作为 property 传入。
mount 方法
mount
可以理解为安装,可以看到第 5662 行,刚才作为 property 传入的 widget(RenderObjectToWidgetAdapter
)执行了 createRenderObject
方法,并且把自己(RenderObjectToWidgetElement
)作为 property 传进方法里。
看到这里,Widget
、Element
、RenderObject
这三个大名鼎鼎的关键词都已经出现了,但他们的关系好乱,我们继续看:
createRenderObject 方法
通过
RenderObjectToWidgetAdapter
的 createRenderObject
方法后,我们得到了 RenderObject
。这个 RenderObject
是什么?通过 1099 行,再到 1090 行,再到 1080 行,我们返回到初始化 RenderObjectToWidgetAdapter
的地方,看看第二个参数是什么:
所以绕了一大圈,我们知道了,通过
createRenderObject
方法拿到的是随着 WidgetsFlutterBinding
一同产生的一个叫 renderView 的 RenderObject
。
_rebuild 方法
刚才的 mount
方法我们才看了一半,接下来的第 1171 行,执行了 _rebuild
方法:
这个方法里执行了一个叫做
updateChild
的方法,这个方法的第二个参数 (widget as RenderObjectToWidgetAdapter<T>).child
,就是我们最开始传入的 App。
updateChild 方法
我们来看看 updateChild
方法是怎么说的:
这个可是尤其重要的一个方法。
inflateWidget 方法
接下来会进到 inflateWidget
方法:
inflateWidget
方法里会用我的 App 来执行 createElement
方法,因为我的 App 是继承的 StatelessWidget
,所以 createElement
方法会建立一个 StatelessElement
并把自己(StatelessWidget
)当成 property 传进 StatelessElement
内来使之构造。所以在这里 newChild 是 StatelessElement
,接着第 3817 行会将 StatelessElement
执行 mount
方法,把 this(RenderView
)传进方法里。上面说到了,mount
可以理解为安装,所以这行方法等于是让 StatelessElement
拿着 RenderObject
(RenderView)。
执行 mount
方法,又回到了这里:
attachRenderObject 方法
接着执行 attachRenderObject
方法:
该方法内,
_findAncestorRenderObjectElement
顾名思义,查找祖先的 RenderObjectElement
,最上面最上面我们还记得,祖先 RenderObjectElement
是 RenderObjectToWidgetElement
。
再进入 RenderObjectToWidgetElement
的 insertRenderObjectChild
方法:
我们来看第 1223 行。
renderObject 是谁呢?renderObject 是 WidgetsFlutterBinding
的 renderView。
child 是谁呢?是我们 App 的 RenderObject
,也就是 StatelessElement
拿着的那个 RenderObject
。
到这里,终于把 App 的 RenderObject
和 WidgetsFlutterBinding
的 RenderObject
绑在了一起。
小结一下:
- 塞了一个
Widget
给runApp
; - 实例化了一个附带
RenderObject
(renderView)的WidgetsFlutterBinding
; - 实例化了一个
RenderObjectToWidgetAdapter
; - 利用
RenderObjectToWidgetAdapter
实例化了一个RenderObjectToWidgetElement
并将RenderObjectToWidgetAdapter
作为RenderObjectToWidgetElement
的 property; RenderObjectToWidgetElement
会通过createElement
产生传入runApp
的Widget
的Element
;- 利用
Widget
产生的Element
通过Widget
产生RenderObject
; - 利用
RenderObjectToWidgetElement
将Widget
的RenderObject
变成WidgetsFlutterBinding
的 renderView 的 child,并将其作为 root widget。
所以我们了解到, RenderObject 是通过 Element 利用 Widget 产生出来的,而 Element 是由 Widget 产生出来的。
做完以上,接着通过 scheduleWarmUpFrame
就会把 widget 提供的配置信息 render 在手机屏幕上了。
RenderObject 到底是个啥
待续
Widget、Element、RenderObject 三者的关系
待续