Flutter 源码阅读 - 三棵树流程分析(三)

291 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

Flutter 源码阅读 - 三棵树流程分析(一)

Flutter 源码阅读 - 三棵树流程分析(二)

一、前言

在上篇文章Flutter 源码阅读 - 三棵树流程分析(二)中我们分析了 RenderObjectWidget 的案例,本篇文章我们主要分析下 StatelessWidgetStatefulWidget 案例。


二、StatelessWidget 案例

我们在 RenderObjectWidget 案例的基础上进行修改,把 ColoredBox 放在 StatelessWidget 中。

void main() {
  runApp(
    const MyApp(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const ColoredBox(
      color: Colors.blue,
    );
  }
}

不出所料,程序运行起来后,UI 界面和案例一是一样的。

image.png

我们首先来看一下 StatelessWidget 的源码,如下图:

image.png

它的内部定义非常简单,创建一个 StatelessElement 作为 createElement 的返回值,然后定义了一个 build 抽象方法,下面我们主要分析一下 build 方法。

在上篇文章中我们讲到在 attachToRenderTree 中会执行 createElement,然后再执行 mount 方法,在 RenderObjectToWidgetElement mount 中会执行 _rebuild 方法,_rebuild 中主要执行了 updateChild 方法,然后执行 inflateWidget(这些流程在上篇文章已经进行过详细分析),下面重点来了,我们来看一下断点调试跟踪一下 newChild.mount(this, newSlot),如图:

image.png

因为此时的 newChild 就是我们在 runApp 中写的 MyAppStatelessWidget createElement 所创建的 StatelessElement, 所以接下来会继续执行 ComponentElement 中的 mount 方法。

image.png

接下来继续执行 _firstBuild,然后再执行 Element 中的 rebuild

image.png

rebuild 中会执行 performRebuild ,此时回到 ComponentElement 中的 performRebuild 方法中,此时我们注意到会执行到 build 方法,然后一路执行到 MyApp 中的 build 方法。

image.png

image.png

image.png

至此我们终于知道 StatelessWidget 中的 build 方法在什么时候执行了了。至于剩下的流程,和上篇文章讲的差不多,我们主要分析一下什么时候执行 build 方法。


三、StatefulWidget 案例

StatelessWidget 案例的基础上我们把 StatelessWidget 直接替换为 StatefulWidget,代码如下:

void main() {
  runApp(
    const MyApp(),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return const ColoredBox(
      color: Colors.blue,
    );
  }
}

运行起来的效果和上面的一样,这里就不再贴图了。

按照惯例我们先来看一下 StatefulWidget 的源码,如下图:

image.png

它的内部定义也非常简单,创建一个 StatefulElement 作为 createElement 的返回值,然后定义了一个 createState 抽象方法。从这里可以看出 StatefulWidget 并不持有 State,只是创建 State

我们大致看一下 StatefulElement 的源码,先大致留意一下红框中的内容,通过以上案例的分析我们可以大胆预测一下,在 inflateWidget 中调用 createElement 方法,在 performRebuild 方法中调用 build 方法。下面我们开始断点调试验证下我们的猜测。

image.png

image.png

image.png

image.png

image.png

上面的断点调试截图可以看出,的确是在 inflateWidget 中调用 createElement 方法,此时将会执行 StatefulElement 构造函数从而执行 MyApp 中的 _MyAppState() 方法。

image.png

image.png

image.png

然后会在 performRebuild 方法中调用 build 方法,最后执行 _MyAppState 的 build 方法。

有关 State 类的分析,这里暂不做解释,有兴趣的话,可以自己断点调试研究一下。


四、总结

上面所讲的 StatelessWidget 、StatefulWidget 以及 ParentDataWidget 、InheritedWidget 这类的 ProxyWidget 本质上都是组合型组件。也就是说除了 RenderObjectWidget 一族的组件,其余的组件全是组合型的组件。