前面我们分析了Widget,发现源码非常简单,主要逻辑就是构建子树,以及是创建Element。 那Element有何神奇?且看Element。

首先我们看下Element家族的继承关系:

flutter EasyRefresh 属性_flutter

我们可以看到Element系列庞大,但跟我们平常开发关系比较大却不多。接下来我们会主要围绕这个继承关系图,逐个分析主要的类。

DiagnosticableTree

这个没什么好说的,就是一堆方便处理调试信息的。Widget也继承这个。

BuildContext

这个我们可能熟悉一些,Widget的build方法有个BuildContext参数,事实上,那个context就是Element,而Element是实现了BuildContext,并暴露给Widget使用

整理了一下BuildContext的方法,主要是一系列获取方法。 访问指定类型祖先和child之类的

//注册依赖祖先InheritWigdet
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
//获取指定类型的祖先InheritWidget  
T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object aspect });
//获取指定类型祖先InteritWidget的Element	
InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();	
//获取指定类型的祖先Widget
T findAncestorWidgetOfExactType<T extends Widget>();
//获取指定类型的祖先State
T findAncestorStateOfType<T extends State>();
//获取指定类型的最远祖先State
T findRootAncestorStateOfType<T extends State>();
//获取指定类型的RendObject
T findAncestorRenderObjectOfType<T extends RenderObject>();
//访问祖先Element
void visitAncestorElements(bool visitor(Element element));
//访问孩子Element
 void visitChildElements(ElementVisitor visitor);

我们可以看到,通过BuildContext可以获取很多关于所在的Widget树、Element树、Reder树的特定信息。

Element

Element是Widget和RederObject的桥梁。关键方法主要有一下这些:

//根据新的newWidget,更新Element。如果无法更新,就新建一个Element
Element updateChild(Element child, Widget newWidget, dynamic newSlot)
//根据newWidget新建一个Element.
Element inflateWidget(Widget newWidget, dynamic newSlot)
//新建的Element挂载到parent时调用此方法.
void mount(Element parent, dynamic newSlot) 
//Element真正执行更新的方法
void update(covariant Widget newWidget)

增加一些说明:

  1. updateChildinflatWidget 主要作用是当Widget树发生变化时, 需要对应地创建Element。 不同的是updateChild做了一些优化,尽可能地复用之前的旧Element。 只有在无法复用的情况下,才调用inflatWidget去直接创建一个Element。 那什么情况可以复用Element呢?主要有:
  • 新的Widget和旧Widget相等
  • 新的Wiget和旧Widget类型相同,且key相等(如果key都为空也相等)

我们平时写Widget时,有时候会忽略key,但关系不大,如果新旧Widget的key都为空,也可以复用Element。
2. 一般新创建一个Element时,会马上调用mount方法。 如果可以复用的场景,则调用update(widget)方法。

接下来的篇章再分析Element的左子树。ComponentElment、StatelessElement、StatefulElement