顺着代码看:
入口函数 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 三者的关系
待续