相关类分析

BuildContext

一个指向小控件树中小控件位置的句柄。见BuildContext 文档

BuildContext对象被传递给WidgetBuilder函数(如StatelessWidget.build),并可从State.context成员中获得。一些静态函数(如showDialogTheme.of等)也采用BuildContext,以便它们可以代表调用小控件执行操作,或获取特定于给定上下文的数据

每个widget都有自己的BuildContext,它成为StatelessWidget.buildState.build函数返回的那个widget的父节点。(同样地,也是RenderObjectWidget的任何子节点的父节点。)

需要特别注意,build方法所在的widget的BuildContext与该build方法返回的widget的BuildContext是不同的。如果需要那个被返回的控件树的子控件的BuildContext,可以使用 Builder 小控件,则传递给 Builder.builder 回调的BuildContext将是 Builder 本身的上下文。

随着小控件在树上移动,特定小控件的 BuildContext 可以随时间改变位置。正因为如此,从该类上的方法返回的值不应在执行单个同步函数之后被缓存。BuildContext对象实际上就是Element对象。BuildContext接口是用来阻止直接操作Element对象的。

BuildContext的常见方法

  • dependOnInheritedWidgetOfExactType({Object aspect}) → T

    获取给定类型T的最近的widget,该widget必须是一个具体的InheritedWidget子类的类型,并将此构建上下文注册到该widget中,这样当该widget发生变化时(或引入该类型的新widget,或该widget消失),此构建上下文将被重建,以便它可以从该widget中获取新的值。

  • findAncestorRenderObjectOfType() → T

    返回最近的祖先 RenderObjectWidget 小控件的 RenderObject 对象,该对象是给定类型 T 的实例。不应从build方法中使用此方法,调用此方法比较耗费性能。

  • findAncestorStateOfType<T extends State<StatefulWidget>>() → T

    返回给定类型T的实例的最近祖先StatefulWidget 控件的State对象。不应从build方法中使用此方法,调用此方法比较耗费性能。

  • findAncestorWidgetOfExactType() → T

    返回给定类型T的最近祖先Widget,它必须是具体Widget子类的类型。调用此方法比较耗费性能。

  • findRenderObject() → RenderObject

    当前小控件的RenderObject。如果小控件是 RenderObjectWidget,则这是小控件为其自身创建的渲染对象。否则,它是第一个后代RenderObjectWidget的渲染对象 。

  • findRootAncestorStateOfType<T extends State<StatefulWidget>>() → T

    返回给定类型 T 的最远祖先 StatefulWidget 控件的State对象。

  • getElementForInheritedWidgetOfExactType() → InheritedElement

    获取给定类型T的最近的widget对应的元素,它必须是一个具体的InheritedWidget子类的类型。如果没有找到这样的元素,则返回null。

  • visitAncestorElements(bool visitor(Element element)) → void

    从此context的小控件的父级开始遍历祖先链,为每个祖先调用参数。回调被赋予对祖先小控件的相应Element对象的引用。当到达根部小控件或回调返回false时,遍历停止。回调不得返回null。这对于检查小控件树很有用。

  • visitChildElements(ElementVisitor visitor) → void

    遍历此小控件的子级。这对于在子节点被构建后应用更改而无需等待下一帧非常有用,尤其是当子节点是已知的,且只有一个子节点时(StatefulWidgets 或 StatelessWidgets 总是如此)。递归调用此方法非常耗费性能,应尽可能避免。

查看UML类图

Element

Element实际上就是BuildContext的实现类。见Element 文档

Element的属性

属性 类型 简述
depth int 保证大于父级的整数(如果有)。树根元素的深度必须大于0。
dirty bool 如果该元素被标记为需要重建,则返回true。
owner BuildOwner 管理该Element生命周期的对象。
renderObject RenderObject 树中此位置(或下方)的渲染对象。如果此对象是一个RenderObjectElement,那么渲染对象就是树中这个位置的对象。否则,这个getter方法将沿着树向下走,直到找到一个RenderObjectElement为止。
size Size 返回的RenderBox的大小。这个getter方法只有在布局阶段完成后才会返回一个有效的结果。因此,从build中调用这个函数是无效的
slot dynamic 由父级设置的信息,用于定义此子级在其父级的子级列表中的位置。仅具有一个子级的Element子类,则该子类的slot应该使用null。
widget Widget 该Element的配置。
  • Element updateChild(Element child, Widget newWidget, dynamic newSlot)

    使用给定的新配置(newWidget)更新给定的子元素(child)

newWidget == null newWidget != null
child == null 返回null 返回一个新的Element
child != null 旧的子元素(child)被移除,返回null 若可能,更新旧的子元素(child),返回child 或新的Element
  • Element inflateWidget(Widget newWidget, dynamic newSlot)

    为给定的widget创建一个element,并将其作为该element的子元素添加到给定的Slot中。如果给定widget具有global key,并且已经存在具有该全局键的widget的元素,则此函数将重用该元素(可能从树中的另一个位置移植它,或者从非活动元素列表中重新激活它),而不是创建一个element

  • void mount(Element parent, dynamic newSlot)

    在给定的父元素的给定Slot位中添加这个元素。当新创建的元素第一次被添加到树上时,框架会调用这个函数,将Element从"initial"生命周期状态转换到 "active"生命周期状态

  • void update(covariant Widget newWidget)

    更改用于配置此Element的widget。当父元素希望使用不同的widget来配置这个元素时,框架会调用这个函数。新的widget保证与旧的widget具有相同的runtimeType。该函数仅在"active"生命周期状态下被调用。

updateChildinflatWidget 主要作用是当Widget树发生变化时, 创建对应的Element。 不同的是updateChild做了一些优化,尽可能地复用之前的旧Element。 只有在无法复用的情况下,才调用inflatWidget去直接创建一个Element。 通常新创建一个Element时,会马上调用mount方法。 如果可以复用的场景,则调用update()方法

当新的Widget和旧Widget相同,或者新的Wiget和旧Widget类型相同,且key相同(如果key都为空也表示相同)时,可复用Element

查看UML类图

Widget

是一个用于描述Element的配置。

Widget是Flutter框架中的核心类层次结构。是用户界面部分的不变描述。可以将Widget扩充为Element,以管理底层渲染树。

Widget本身没有可变的状态(它们的所有字段都必须为final)。如果希望将可更改的状态与Widget关联起来,请考虑使用StatefulWidget,每当它扩充成一个Element并被合并到树中时,它就会创建一个State对象(通过StatefulWidget.createState)。

UML类图

RenderObject

渲染树中的对象。见RenderObject 文档

RenderObject具有一个parent属性,并具有一个名为parentData的插槽,父RenderObject可以在其中存储特定于孩子的数据,例如,孩子的位置。 RenderObject类还实现基本的布局和绘制协议。

然而,RenderObject类并没有定义子模型(例如,一个节点是否有零个、一个或多个子节点)。它也没有定义坐标系(例如子节点是以笛卡尔坐标定位,还是以极坐标定位等),也没有定义具体的布局协议。它的子类RenderBox引入了布局系统并使用笛卡尔坐标系。

通常,Flutter渲染对象树的根是RenderView。 该对象有一个child,必须是RenderBox。因此,如果你想在渲染树中拥有一个自定义的RenderObject子类,你有两个选择:要么你需要替换RenderView本身,要么你需要一个继承自RenderBox的自定义类。 (后者是更常见的情况。)

查看UML类图

关于布局

布局协议从Constraints类派生。

performLayout方法应该接受约束,并应用它们。布局算法的输出是在对象上设置的字段,这些字段描述了对象的几何形状,以便于父类的布局。例如,对于RenderBox,输出是RenderBox.size字段。仅当父级在子级上调用layout时并将parentUsesSize指定为true时,此输出才应由父级读取。只要渲染对象上发生任何会影响该对象布局的更改,则应调用markNeedsLayout

Layer

参见 Layer 文档

图层类。在绘制过程中,渲染树生成一棵合成图层树,这些图层被传到到引擎中并由合成器显示。此类是所有图层的基类。大多数图层可以更改其属性,并且可以将图层移动到其他父对象

要合成树,需创建一个SceneBuilder对象,将其传递给根Layer对象的addToScene方法,然后调用 SceneBuilder.build获得一个Scene。然后可以使用Window.render来绘制一个Scene。

Scene对象代表合成场景的不透明对象。通过Window.render方法显示到屏幕上。实际上它是上层框架和底层引擎之间传递的数据结构,对应 Engine中的 scene.cc 结构。

查看UML类图

BuildOwner

Widget框架的管理类。

该类跟踪哪些widget需要重建,并处理其他适用于widgets树的任务,如管理树的非活动元素列表,并在调试时的热重载期间在必要时触发 "reassemble "命令。

主构建所有者通常由WidgetsBinding拥有,并与构建/布局/绘制管道的其余部分一起由操作系统驱动。

可以构建其他构建所有者来管理屏幕外的小组件树。

要为树分配构建所有者,请在小组件树的根元素上使用 RootRenderObjectElement.assignOwner 方法。

PipelineOwner

用于管理渲染管道。

管道所有者提供了一个驱动渲染管道的接口,并存储了关于在管道的每个阶段中哪些渲染对象请求被访问的状态。


公众号“编程之路从0到1”

20190301102949549

Copyright © Arcticfox 2020 all right reserved,powered by Gitbook文档修订于: 2022-05-01 12:00:54

results matching ""

    No results matching ""