likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 53

日常工作中我们所编写的一个个 Widget,它到底是什么东西、以及它是如何展现在用户面前的? 本系列文章将会通过一些小的案例以及源码来进行分析 Flutter 中 WidgetElementRenderObject 三棵树之间的关系以及它们各自的作用(注意:本系列文章对 Layer 暂不做探讨)。

本篇文章将会通过源码先对他们做一个简单的分类,让读者先留下一个印象。在后续的文章中将会逐渐进行深入分析。


一、 Widget 的分类

Flutter 中是通过 Widget 嵌套来进行构建 UI 的(Flutter 中万物皆 Widget),我们首先来看下 Widget 的分类。

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

通过查看 Flutter 源码我们可以得出以上总结,Widget 大致可以分为 RenderObjectWidget 和组合型 Widget(根据有没有对应的 RenderObject来进行分类)。

RenderObjectWidget 又可以分为 LeafRenderObjectWidgetSingleChildRenderObjectWidgetMultiChildRenderObjectWidget 等。

通过下图源码我们可以看出 RenderObjectWidget 抽象类主要包含四个方法:createElementcreateRenderObjectupdateRenderObjectdidUnmountRenderObject,其中 createElementcreateRenderObject 为抽象方法,需要子类去实现。

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

RenderObjectWidgets provide the configuration for [RenderObjectElement]s, which wrap [RenderObject]s, which provide the actual rendering of the application.

通过注释我们可以看出 RenderObjectWidget 主要是为 RenderObjectElement提供配置,创建 RenderObject

组合型 Widget 又可以分为 StatelessWidgetStatefulWidgetProxyWidget等。这里我们主要主要看下 StatelessWidgetStatefulWidget

StatelessWidget主要有 createElementbuild 方法,其中 createElement 返回了一个 StatelessElementbuild 则为抽象方法,就是我们经常实现的一个方法。

StatefulWidget 主要有 createElementcreateState 方法,其中 其中 createElement 返回了一个 StatefulElementcreateState也是一个抽象方法,也是我们我们经常实现的一个方法。通过 StatelessWidgetStatefulWidgetRenderObjectWidget 的源码进行对比我们发现主要是 RenderObjectWidget 多了 createRenderObject 抽象方法。那么 createElementcreateRenderObject 主要是做什么的,又有哪些作用呢?在这里先留下一个疑问,后续将会进行讲解。

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


二、 Element 的分类

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

通过上面对 Widget 的了解,我们可以看出它主要就是为了创建 Element 而生的。相应的,每一个细分的 xxxWidget 都有对应的 xxxElement

比如 StatelessWidget -> StatelessElementStatefulWidget -> StatefulElementInheritedWidget -> InheritedElementLeafRenderObjectWidget -> LeafRenderObjectElementSingleChildRenderObjectWidget -> SingleChildRenderObjectElementMultiChildRenderObjectWidget -> MultiChildRenderObjectElement等。

每个 xxxElement 最终都会通过继承 ComponentElementRenderObjectElement 来继承 Element 抽象类。这里与上面讲到的 Widget 相对应,组合型 Widget 对应 ComponentElenentRenderObjectWidget 对应 RenderObjectElement

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

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

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

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

通过 Element 抽象类的源码我们可以发现,Element 中持有 WidgetRenderObject

// 简化后的 Element 源码
abstract class Element extends DiagnosticableTree implements BuildContext {
  Element(Widget widget)
    : assert(widget != null),
      _widget = widget;

    @override
    Widget get widget => _widget!;
    Widget? _widget;

    RenderObject? get renderObject {
      RenderObject? result;
      void visit(Element element) {
        assert(result == null);
        if (element._lifecycleState == _ElementLifecycle.defunct) {
          return;
        } else if (element is RenderObjectElement) {
          result = element.renderObject;
        } else {
          element.visitChildren(visit);
        }
      }
      visit(this);
      return result;
    }
}

三、 RenderObject 的分类

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

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

通过源码中的注释可以看出 RenderObjectWithChildMixin 是为了渲染单子节点而生,ContainerRenderObjectMixin 是为了渲染多子节点而生,RelayoutWhenSystemFontsChangeMixin 是为了配合系统字体更改而生的。


四、最后

最后附上一张 WidgetElementRenderObject 它们的全图,方便读者进行对比查看。 Flutter 源码阅读 -  三棵树流程分析(一)

转载自:https://juejin.cn/post/7169495060097007630
评论
请登录