在本系列文章的前面三篇文章中,已经分别介绍Flutter的三种核心元素:Widget,Element,和RenderObject。并介绍了它们之间的关系。在这篇文章中,将在前面文章的基础上,对Flutter中很是出名的概念“Widget,Element,RenderObject树”进行剖析,以此加深读者对Flutter Framework的理解。markdown
学习Flutter的时候常常会遇到一个概念:Widget,Element,RenderObject树。那什么是Widget,Element,RenderObject树呢?Flutter中的Widget,Element,RenderObject树指的是:Widget Tree, Element Tree, RenderObject Tree。从前面几篇文章能够知道,它们的做用分别以下:架构
Widget Tree是整个UI界面的配置,Flutter开发者经过Widget Tree告诉Framework想要绘制的UI界面是什么样的,这棵树是咱们主要打交道的对象。app
Element Tree是经过Widget Tree生成的,其主要做用是维护UI元素的树形结构,并将Widget和RenderObject关联到树上。框架
RenderObject Tree也是经过Widget Tree生成的,其主要做用是负责界面的绘制和布局,是属于底层系统,Flutter开发者通常不须要直接操做该树。 为了加深对这Widget,Element,RenderObject树的理解,下面将使用一个例子进行讲解。less
示例代码以下:ide
class TreeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("tree test", textDirection: TextDirection.ltr)
);
}
}
复制代码
该示例很简单,在页面中间显示一个Text,文案为tree test。其运行结果以下:函数
其代码对应的Widget Tree,Element Tree,RenderObject Tree的示意图以下:oop
结合本系列文章的前面三篇:Flutter框架分析(二)--Widget,Flutter框架分析(三)--Element,Flutter框架分析(四)-RenderObject。由上图能够看出:布局
在上图中一个值得注意的地方是Text,从图中能够看到它有个子Widget:RichText,可是咱们在示例中只定义了一个Text组件,这是怎么回事呢?咱们能够追踪下源码。post
Text的定义以下:
class Text extends StatelessWidget 复制代码
所以它只是一个用于组合其余更基础的Widget,真正控制文案属性的是在build函数中定义的RichText,其源码以下:
@override
Widget build(BuildContext context) {
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
TextStyle effectiveTextStyle = style;
if (style == null || style.inherit)
effectiveTextStyle = defaultTextStyle.style.merge(style);
if (MediaQuery.boldTextOverride(context))
effectiveTextStyle = effectiveTextStyle.merge(const TextStyle(fontWeight: FontWeight.bold));
Widget result = RichText(
textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,
textDirection: textDirection, // RichText uses Directionality.of to obtain a default if this is null.
locale: locale, // RichText uses Localizations.localeOf to obtain a default if this is null
softWrap: softWrap ?? defaultTextStyle.softWrap,
overflow: overflow ?? defaultTextStyle.overflow,
textScaleFactor: textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
maxLines: maxLines ?? defaultTextStyle.maxLines,
strutStyle: strutStyle,
textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis,
textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.of(context),
applyTextScaleFactorToWidgetSpan: _applyTextScaleFactorToWidgetSpan,
text: TextSpan(
style: effectiveTextStyle,
text: data,
children: textSpan != null ? <InlineSpan>[textSpan] : null,
),
);
if (semanticsLabel != null) {
result = Semantics(
textDirection: textDirection,
label: semanticsLabel,
child: ExcludeSemantics(
child: result,
),
);
}
return result;
}
复制代码
因此在Widget Tree中能够看到Text的child是RichText。
上文已经说过,Widget Tree中的Widget和Element Tree中的Element关系是一一对应的,可是咱们在Flutter框架分析(二)--Widget一文中曾经说过,一个Widget对象能够对应多个Element对象。那这不是互相矛盾了吗?其实不是的,一个Widget对象并不等同于一个Widget Tree中的Widget对象,由于在Widget Tree中还有个位置属性(Slot)。一个Widget对象加上其在Widget Tree中的位置,才相对于一个Widget Tree中的Widget对象。
如下是一个Widget对象对应多个Element对象的一个示例:
class SameWidgetMultiElementWidget1 extends StatefulWidget {
@override
_SameWidgetMultiElementWidgetState createState() => new _SameWidgetMultiElementWidgetState();
}
class _SameWidgetMultiElementWidgetState extends State<SameWidgetMultiElementWidget1> {
int count = 0;
@override
Widget build(BuildContext context) {
Text testText = Text("multi element");
return Column(
children: <Widget>[
testText,
testText,
],
);
}
}
复制代码
其对应的Widget Tree和Element Tree以下:
在上面示例中,左边是Widget Tree,右边是Element Tree。在Widget Tree中,Column有两个子节点,可是这两个子节点使用的是同一个Text对象,所以这个Text对象出如今两个不一样的位置(Slot),此时在Element Tree会生成两个不一样的StatelessElement对象,即一个Text对象对应两个StatelessElement对象。
注意该Widget Tree和Element Tree未包含根节点。
本文主要介绍了Flutter中的常见概念:Widget Tree, Element Tree, RenderObject Tree。并经过一个例子,讲解了这三棵树之间的关系。本文的重点以下:
Flutter architectural overview
Flutter框架分析(一)--架构总览
Flutter框架分析(二)-- Widget
Flutter框架分析(三)-- Element
Flutter框架分析(四)-RenderObject
Flutter框架分析(六)-Constraint
Flutter框架分析(七)-relayoutBoundary
Flutter框架分析(八)-Platform Channel
Flutter框架分析- Parent Data
Flutter框架分析 -InheritedWidget