Widget 源码分析
abstract class Widget extends DiagnosticableTree {const Widget({ this.key });final Key? key;@protected@factoryElement createElement();@overrideString toStringShort() {final String type = objectRuntimeType(this, 'Widget');return key == null ? type : '$type-$key';}@overridevoid debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;}@override@nonVirtualbool operator ==(Object other) => super == other;@override@nonVirtualint get hashCode => super.hashCode;static bool canUpdate(Widget oldWidget, Widget newWidget) {return oldWidget.runtimeType == newWidget.runtimeType&& oldWidget.key == newWidget.key;}// 返回特定 `Widget` 具体子类型的数字编码。// 这在 `Element.updateChild` 中用于确定热重载是否修改了// 已安装元素配置的超类。 每个 `Widget` 的编码// 必须匹配 `Element._debugConcreteSubtype` 中对应的 `Element` 编码。static int _debugConcreteSubtype(Widget widget) {return widget is StatefulWidget ? 1 :widget is StatelessWidget ? 2 :0;}}
这里 Widget 会创建对应 的 Element,StatelessWidget 会创建 StatelessElement 类型的 Element,而 StatefulWidget 会创建 StatefulElement 类型的 Element。
abstract class StatelessWidget extends Widget {const StatelessWidget({ super.key });@overrideStatelessElement createElement() => StatelessElement(this);@protectedWidget build(BuildContext context);}
abstract class StatefulWidget extends Widget {const StatefulWidget({ super.key });@overrideStatefulElement createElement() => StatefulElement(this);@protected@factoryState createState();}
从这里可以看出有 状态组件 和 无状态 组件就差别在于是否有配置信息。
State 源码分析
abstract class State<T extends StatefulWidget> with Diagnosticable {T get widget => _widget!;T? _widget;/// 此状态对象的生命周期中的当前阶段。_StateLifecycle _debugLifecycleState = _StateLifecycle.created;/// 为那个特定的 [Widget] 创建。bool _debugTypesAreRight(Widget widget) => widget is T;/// 当前 Widget 在树中所在的位置BuildContext get context {assert(() {if (_element == null) {throw FlutterError('This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n''Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',);}return true;}());return _element!;}StatefulElement? _element;// 当前 Widget 是否被挂载到树上bool get mounted => _element != null;/// 当这个对象被插入到树中时调用。/// 将为每个 [State] 对象仅调用一次此方法@protected@mustCallSupervoid initState() {assert(_debugLifecycleState == _StateLifecycle.created);}/// 当 此对象 配置发生变化时调用@mustCallSuper@protectedvoid didUpdateWidget(covariant T oldWidget) { }/// 调用此方法将 调用 build 方法 ;reassemble 方法并不需要做些什么@protected@mustCallSupervoid reassemble() { }/// 通知框架这个对象的内部状态已经改变。/// 调用 此方法可能会影响用户界面/// 子树也会因此父 Widget 调用 SetState 而 build@protectedvoid setState(VoidCallback fn) {assert(fn != null);assert(() {if (_debugLifecycleState == _StateLifecycle.defunct) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('setState() called after dispose(): $this'),ErrorDescription('This error happens if you call setState() on a State object for a widget that ''no longer appears in the widget tree (e.g., whose parent widget no longer ''includes the widget in its build). This error can occur when code calls ''setState() from a timer or an animation callback.',),ErrorHint('The preferred solution is ''to cancel the timer or stop listening to the animation in the dispose() ''callback. Another solution is to check the "mounted" property of this ''object before calling setState() to ensure the object is still in the ''tree.',),ErrorHint('This error might indicate a memory leak if setState() is being called ''because another object is retaining a reference to this State object ''after it has been removed from the tree. To avoid memory leaks, ''consider breaking the reference to this object during dispose().',),]);}if (_debugLifecycleState == _StateLifecycle.created && !mounted) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('setState() called in constructor: $this'),ErrorHint('This happens when you call setState() on a State object for a widget that '"hasn't been inserted into the widget tree yet. It is not necessary to call "'setState() in the constructor, since the state is already assumed to be dirty ''when it is initially created.',),]);}return true;}());final Object? result = fn() as dynamic;assert(() {if (result is Future) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('setState() callback argument returned a Future.'),ErrorDescription('The setState() method on $this was called with a closure or method that ''returned a Future. Maybe it is marked as "async".',),ErrorHint('Instead of performing asynchronous work inside a call to setState(), first ''execute the work (without updating the widget state), and then synchronously ''update the state inside a call to setState().',),]);}return true;}());_element!.markNeedsBuild();}/// 当这个对象从树中移除时调用。@protected@mustCallSupervoid deactivate() { }/// 当这个对象被重新插入到树中时调用@protected@mustCallSupervoid activate() { }/// 当此对象从树中永久删除时调用。@protected@mustCallSupervoid dispose() {assert(_debugLifecycleState == _StateLifecycle.ready);assert(() {_debugLifecycleState = _StateLifecycle.defunct;return true;}());}/// 描述这个小部件所代表的用户界面部分。@protectedWidget build(BuildContext context);/// 当此 [State] 对象的依赖项发生更改时调用。/// 在 initState() 后,调用@protected@mustCallSupervoid didChangeDependencies() { }@overridevoid debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);assert(() {properties.add(EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));return true;}());properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));properties.add(ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));}}
state 在 StatefulWidget 被继承的时候被创建,并在 StatefulElement 构造函数里被再次创建,并被对应的 StatefulElement 持有。State 让 StatelessWidget 和 StatefulWidget 做出本质的区别,Widget 的 配置信息可否复用(在 Widget.runtimeType 和 Widget.key 以及在Element tree中节点位置 均相同的情况下)。因此结合 BuildContext 源码分析得出 State 和 BuildContext 是互补关系,State 是当前 Widget 的配置信息,而 BuildContext 是储存当前 Widget && Element 的 上至 root 下至节点最底层 child 的信息,BuildContext 和 State 在Element 实例化后就被永久绑定,从 Element tree 移除 对应的 Element 后,State 和 BuildContext 的也就解绑。
Element 源码分析
BuildContext 源码分析
BuildContext 对象实际上是 [Element] 对象。
abstract class BuildContext {/// The current configuration of the [Element] that is this [BuildContext].Widget get widget;/// 管理此上下文的渲染管道。BuildOwner? get owner;/// 当前是否正在更新 Widget 或 渲染树bool get debugDoingBuild;/// Widget 的当前 [RenderObject]RenderObject? findRenderObject();/// [findRenderObject] 返回的 [RenderBox] 的大小。Size? get size;/// 用 [ancestor] 注册这个构建上下文InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });/// 获取给定类型`T`的最近的 Widget ,它必须是a的类型/// 具体的 [InheritedWidget] 子类,并将此构建上下文注册到/// 该 Widget 使得当该 Widget 更改时(或该 Widget 的新 Widget/// 类型被引入,或者 Widget 消失),这个构建上下文是/// 重建,以便它可以从该 Widget 获取新值。T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect });/// 获取与给定类型`T`最近的 Widget 对应的 Element,/// 必须是具体的 [InheritedWidget] 子类的类型。/// 如果没有找到这样的 Element,则返回 null。InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();/// 返回给定类型`T`的最近的祖先小部件,它必须是/// 具体 [Widget] 子类的类型。T? findAncestorWidgetOfExactType<T extends Widget>();/// 返回最近的祖先 [StatefulWidget] 小部件的 [State] 对象/// 这是给定类型 `T` 的一个实例。T? findAncestorStateOfType<T extends State>();/// 返回最远祖先 [StatefulWidget] 小部件的 [State] 对象/// 这是给定类型 `T` 的一个实例。T? findRootAncestorStateOfType<T extends State>();/// 返回最近的祖先 [RenderObjectWidget] Widget 的 [RenderObject] 对象/// 这是给定类型 `T` 的一个实例。T? findAncestorRenderObjectOfType<T extends RenderObject>();/// 遍历祖先链,从这个构建上下文的父节点开始/// 回调被赋予一个对祖先 Widget 对应的 [Element] 对象的引用。void visitAncestorElements(bool Function(Element element) visitor);/// 遍历这个 Widget 的子节点。void visitChildElements(ElementVisitor visitor);/// 在给定的构建上下文中开始冒泡这个通知。void dispatchNotification(Notification notification);/// 返回与当前构建 context 关联的 [Element] 的描述。DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});/// 返回与当前构建 context 关联的 [Widget] 的描述。DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});/// 添加当前缺少的特定类型小部件的描述List<DiagnosticsNode> describeMissingAncestor({ required Type expectedAncestorType });/// 从特定的 [Element] 添加所有权链的描述DiagnosticsNode describeOwnershipChain(String name);}
/// 节选代码abstract class Element extends DiagnosticableTree implements BuildContext {/// 此 Element 的配置。@overrideWidget get widget => _widget!;Widget? _widget;/// 管理此 Element 生命周期的对象。@overrideBuildOwner? get owner => _owner;BuildOwner? _owner;/// 树中此位置(或下方)的 renderObject。RenderObject? get renderObject {RenderObject? result;void visit(Element element) {assert(result == null); // this verifies that there's only one childif (element._lifecycleState == _ElementLifecycle.defunct) {return;} else if (element is RenderObjectElement) {result = element.renderObject;} else {element.visitChildren(visit);}}visit(this);return result;}/// 使用给定的新配置更新给定的子节点。Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {if (newWidget == null) {if (child != null)deactivateChild(child);return null;}final Element newChild;if (child != null) {bool hasSameSuperclass = true;assert(() {final int oldElementClass = Element._debugConcreteSubtype(child);final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);hasSameSuperclass = oldElementClass == newWidgetClass;return true;}());if (hasSameSuperclass && child.widget == newWidget) {if (child.slot != newSlot)updateSlotForChild(child, newSlot);newChild = child;} else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {if (child.slot != newSlot)updateSlotForChild(child, newSlot);final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);if (isTimelineTracked) {Map<String, String>? debugTimelineArguments;assert(() {if (kDebugMode && debugEnhanceBuildTimelineArguments) {debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();}return true;}());Timeline.startSync('${newWidget.runtimeType}',arguments: debugTimelineArguments,);}child.update(newWidget);if (isTimelineTracked)Timeline.finishSync();assert(child.widget == newWidget);assert(() {child.owner!._debugElementWasRebuilt(child);return true;}());newChild = child;} else {deactivateChild(child);assert(child._parent == null);newChild = inflateWidget(newWidget, newSlot);}} else {newChild = inflateWidget(newWidget, newSlot);}assert(() {if (child != null)_debugRemoveGlobalKeyReservation(child);final Key? key = newWidget.key;if (key is GlobalKey) {assert(owner != null);owner!._debugReserveGlobalKeyFor(this, newChild, key);}return true;}());return newChild;}/// 将此元素添加到给定父级的给定槽中的树中。void mount(Element? parent, Object? newSlot) {assert(_lifecycleState == _ElementLifecycle.initial);assert(widget != null);assert(_parent == null);assert(parent == null || parent._lifecycleState == _ElementLifecycle.active);assert(slot == null);_parent = parent;_slot = newSlot;_lifecycleState = _ElementLifecycle.active;_depth = _parent != null ? _parent!.depth + 1 : 1;if (parent != null) {_owner = parent.owner;}assert(owner != null);final Key? key = widget.key;if (key is GlobalKey) {owner!._registerGlobalKey(key, this);}_updateInheritance();attachNotificationTree();}/// 更改用于配置此 Element 的 Widget。@mustCallSupervoid update(covariant Widget newWidget) {assert(_lifecycleState == _ElementLifecycle.active&& widget != null&& newWidget != null&& newWidget != widget&& depth != null&& Widget.canUpdate(widget, newWidget),);assert(() {_debugForgottenChildrenWithGlobalKey?.forEach(_debugRemoveGlobalKeyReservation);_debugForgottenChildrenWithGlobalKey?.clear();return true;}());_widget = newWidget;}/// 将 [renderObject] 添加到render tree中 `newSlot` 指定的位置。void attachRenderObject(Object? newSlot) {assert(_slot == null);visitChildren((Element child) {child.attachRenderObject(newSlot);});_slot = newSlot;}/// 从渲染树中移除 [renderObject]。void detachRenderObject() {visitChildren((Element child) {child.detachRenderObject();});_slot = null;}/// 返回 与此 Element 对应的 renderObjectRenderObject? findRenderObject() {assert(() {if (_lifecycleState != _ElementLifecycle.active) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('Cannot get renderObject of inactive element.'),ErrorDescription('In order for an element to have a valid renderObject, it must be ''active, which means it is part of the tree.\n''Instead, this element is in the $_lifecycleState state.\n''If you called this method from a State object, consider guarding ''it with State.mounted.',),describeElement('The findRenderObject() method was called for the following element'),]);}return true;}());return renderObject;}/// 当这个 Element 的依赖改变时调用。@mustCallSupervoid didChangeDependencies() {assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-opassert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));markNeedsBuild();}/// 将元素标记为脏并将其添加到 Widget 的全局列表中/// 在下一帧重建。void markNeedsBuild() {assert(_lifecycleState != _ElementLifecycle.defunct);if (_lifecycleState != _ElementLifecycle.active)return;assert(owner != null);assert(_lifecycleState == _ElementLifecycle.active);assert(() {if (owner!._debugBuilding) {assert(owner!._debugCurrentBuildTarget != null);assert(owner!._debugStateLocked);if (_debugIsInScope(owner!._debugCurrentBuildTarget!))return true;if (!_debugAllowIgnoredCallsToMarkNeedsBuild) {final List<DiagnosticsNode> information = <DiagnosticsNode>[ErrorSummary('setState() or markNeedsBuild() called during build.'),ErrorDescription('This ${widget.runtimeType} widget cannot be marked as needing to build because the framework ''is already in the process of building widgets. A widget can be marked as ''needing to be built during the build phase only if one of its ancestors ''is currently building. This exception is allowed because the framework ''builds parent widgets before children, which means a dirty descendant ''will always be built. Otherwise, the framework might not visit this ''widget during this build phase.',),describeElement('The widget on which setState() or markNeedsBuild() was called was'),];if (owner!._debugCurrentBuildTarget != null)information.add(owner!._debugCurrentBuildTarget!.describeWidget('The widget which was currently being built when the offending call was made was'));throw FlutterError.fromParts(information);}assert(dirty); // can only get here if we're not in scope, but ignored calls are allowed, and our call would somehow be ignored (since we're already dirty)} else if (owner!._debugStateLocked) {assert(!_debugAllowIgnoredCallsToMarkNeedsBuild);throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),ErrorDescription('This ${widget.runtimeType} widget cannot be marked as needing to build ''because the framework is locked.',),describeElement('The widget on which setState() or markNeedsBuild() was called was'),]);}return true;}());if (dirty)return;_dirty = true;owner!.scheduleBuildFor(this);}/// 使 Widget 自行更新。void rebuild() {assert(_lifecycleState != _ElementLifecycle.initial);if (_lifecycleState != _ElementLifecycle.active || !_dirty)return;assert(() {debugOnRebuildDirtyWidget?.call(this, _debugBuiltOnce);if (debugPrintRebuildDirtyWidgets) {if (!_debugBuiltOnce) {debugPrint('Building $this');_debugBuiltOnce = true;} else {debugPrint('Rebuilding $this');}}return true;}());assert(_lifecycleState == _ElementLifecycle.active);assert(owner!._debugStateLocked);Element? debugPreviousBuildTarget;assert(() {debugPreviousBuildTarget = owner!._debugCurrentBuildTarget;owner!._debugCurrentBuildTarget = this;return true;}());performRebuild();assert(() {assert(owner!._debugCurrentBuildTarget == this);owner!._debugCurrentBuildTarget = debugPreviousBuildTarget;return true;}());assert(!_dirty);}/// 检测是否更新Element@protected@pragma('vm:prefer-inline')Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {if (newWidget == null) {if (child != null)deactivateChild(child);return null;}final Element newChild;if (child != null) {bool hasSameSuperclass = true;assert(() {final int oldElementClass = Element._debugConcreteSubtype(child);final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);hasSameSuperclass = oldElementClass == newWidgetClass;return true;}());if (hasSameSuperclass && child.widget == newWidget) {if (child.slot != newSlot)updateSlotForChild(child, newSlot);newChild = child;} else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {if (child.slot != newSlot)updateSlotForChild(child, newSlot);final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);if (isTimelineTracked) {Map<String, String>? debugTimelineArguments;assert(() {if (kDebugMode && debugEnhanceBuildTimelineArguments) {debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();}return true;}());Timeline.startSync('${newWidget.runtimeType}',arguments: debugTimelineArguments,);}child.update(newWidget);if (isTimelineTracked)Timeline.finishSync();assert(child.widget == newWidget);assert(() {child.owner!._debugElementWasRebuilt(child);return true;}());newChild = child;} else {deactivateChild(child);assert(child._parent == null);newChild = inflateWidget(newWidget, newSlot);}} else {newChild = inflateWidget(newWidget, newSlot);}assert(() {if (child != null)_debugRemoveGlobalKeyReservation(child);final Key? key = newWidget.key;if (key is GlobalKey) {assert(owner != null);owner!._debugReserveGlobalKeyFor(this, newChild, key);}return true;}());return newChild;}}
当前 Element 所依赖的配置 发生变化时,会把当前 Element 的 _dirty 标致为 true ,加入待渲染管道,在下一帧渲染。
StatelessElement 源码分析
class StatelessElement extends ComponentElement {StatelessElement(StatelessWidget super.widget);@overrideWidget build() => (widget as StatelessWidget).build(this);@overridevoid update(StatelessWidget newWidget) {super.update(newWidget);assert(widget == newWidget);_dirty = true;rebuild();}}
根据 StatelessElement 源码得知,在 StatelessWidget 的配置信息发生变化时,当前 StatelessElement 的 脏点 会被标记为 true ,在下一帧会被重新刷新,以及刷新当前 Widget 的子组件。因此尽量在Widget tree中变化少的节点使用 StatelessWidget 。
StatefulElement 源码分析
class StatefulElement extends ComponentElement {StatefulElement(StatefulWidget widget): _state = widget.createState(),super(widget) {assert(() {if (!state._debugTypesAreRight(widget)) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>'),ErrorDescription('The createState function for ${widget.runtimeType} returned a state ''of type ${state.runtimeType}, which is not a subtype of ''State<${widget.runtimeType}>, violating the contract for createState.',),]);}return true;}());assert(state._element == null);state._element = this;assert(state._widget == null,'The createState function for $widget returned an old or invalid state ''instance: ${state._widget}, which is not null, violating the contract ''for createState.',);state._widget = widget;assert(state._debugLifecycleState == _StateLifecycle.created);}/// 创建 State@overrideWidget build() => state.build(this);/// The [State] instance associated with this location in the tree.////// There is a one-to-one relationship between [State] objects and the/// [StatefulElement] objects that hold them. The [State] objects are created/// by [StatefulElement] in [mount].State<StatefulWidget> get state => _state!;State<StatefulWidget>? _state;/// 热重载@overridevoid reassemble() {if (_debugShouldReassemble(_debugReassembleConfig, _widget)) {state.reassemble();}super.reassemble();}@overridevoid _firstBuild() {assert(state._debugLifecycleState == _StateLifecycle.created);try {_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);final Object? debugCheckForReturnedFuture = state.initState() as dynamic;assert(() {if (debugCheckForReturnedFuture is Future) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('${state.runtimeType}.initState() returned a Future.'),ErrorDescription('State.initState() must be a void method without an `async` keyword.'),ErrorHint('Rather than awaiting on asynchronous work directly inside of initState, ''call a separate method to do this work without awaiting it.',),]);}return true;}());} finally {_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);}assert(() {state._debugLifecycleState = _StateLifecycle.initialized;return true;}());state.didChangeDependencies();assert(() {state._debugLifecycleState = _StateLifecycle.ready;return true;}());super._firstBuild();}/// 更改配置信息,重建 Element@overridevoid performRebuild() {if (_didChangeDependencies) {state.didChangeDependencies();_didChangeDependencies = false;}super.performRebuild();}/// 更新 当前 Element@overridevoid update(StatefulWidget newWidget) {super.update(newWidget);assert(widget == newWidget);final StatefulWidget oldWidget = state._widget!;_dirty = true;state._widget = widget as StatefulWidget;try {_debugSetAllowIgnoredCallsToMarkNeedsBuild(true);final Object? debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic;assert(() {if (debugCheckForReturnedFuture is Future) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('${state.runtimeType}.didUpdateWidget() returned a Future.'),ErrorDescription( 'State.didUpdateWidget() must be a void method without an `async` keyword.'),ErrorHint('Rather than awaiting on asynchronous work directly inside of didUpdateWidget, ''call a separate method to do this work without awaiting it.',),]);}return true;}());} finally {_debugSetAllowIgnoredCallsToMarkNeedsBuild(false);}rebuild();}/// 激活 Element@overridevoid activate() {super.activate();state.activate();// Since the State could have observed the deactivate() and thus disposed of// resources allocated in the build method, we have to rebuild the widget// so that its State can reallocate its resources.assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-opmarkNeedsBuild();}/// Element 消活@overridevoid deactivate() {state.deactivate();super.deactivate();}/// 把 Element 从 tree 中取消挂载@overridevoid unmount() {super.unmount();state.dispose();assert(() {if (state._debugLifecycleState == _StateLifecycle.defunct)return true;throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('${state.runtimeType}.dispose failed to call super.dispose.'),ErrorDescription('dispose() implementations must always call their superclass dispose() method, to ensure ''that all the resources used by the widget are fully released.',),]);}());state._element = null;// Release resources to reduce the severity of memory leaks caused by// defunct, but accidentally retained Elements._state = null;}@overrideInheritedWidget dependOnInheritedElement(Element ancestor, { Object? aspect }) {assert(ancestor != null);assert(() {final Type targetType = ancestor.widget.runtimeType;if (state._debugLifecycleState == _StateLifecycle.created) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called before ${state.runtimeType}.initState() completed.'),ErrorDescription('When an inherited widget changes, for example if the value of Theme.of() changes, '"its dependent widgets are rebuilt. If the dependent widget's reference to "'the inherited widget is in a constructor or an initState() method, ''then the rebuilt dependent widget will not reflect the changes in the ''inherited widget.',),ErrorHint('Typically references to inherited widgets should occur in widget build() methods. Alternatively, ''initialization based on inherited widgets can be placed in the didChangeDependencies method, which ''is called after initState and whenever the dependencies change thereafter.',),]);}if (state._debugLifecycleState == _StateLifecycle.defunct) {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called after dispose(): $this'),ErrorDescription('This error happens if you call dependOnInheritedWidgetOfExactType() on the ''BuildContext for a widget that no longer appears in the widget tree ''(e.g., whose parent widget no longer includes the widget in its ''build). This error can occur when code calls ''dependOnInheritedWidgetOfExactType() from a timer or an animation callback.',),ErrorHint('The preferred solution is to cancel the timer or stop listening to the ''animation in the dispose() callback. Another solution is to check the ''"mounted" property of this object before calling ''dependOnInheritedWidgetOfExactType() to ensure the object is still in the ''tree.',),ErrorHint('This error might indicate a memory leak if ''dependOnInheritedWidgetOfExactType() is being called because another object ''is retaining a reference to this State object after it has been ''removed from the tree. To avoid memory leaks, consider breaking the ''reference to this object during dispose().',),]);}return true;}());return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);}bool _didChangeDependencies = false;/// 复用 配置信息@overridevoid didChangeDependencies() {super.didChangeDependencies();_didChangeDependencies = true;}@overrideDiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {return _ElementDiagnosticableTreeNode(name: name,value: this,style: style,stateful: true,);}@overridevoid debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', _state, defaultValue: null));}}
StatefulElement 在 首次构建的时候,State.didChangeDependencies( )就被调用,以及在消活时,调用 state.deactivate( ),再被从Element tree 移除挂载时,调用 state.dispose( ),永久删除 Widget,释放资源。因此得出 StatefulWidget 的生命周期为 :
RenderObject 源码分析
// 节选代码abstract class RenderObject extends AbstractNode withDiagnosticableTreeMixin implements HitTestTarget {RenderObject() {_needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;}/// 热重载void reassemble() {markNeedsLayout();markNeedsCompositingBitsUpdate();markNeedsPaint();markNeedsSemanticsUpdate();visitChildren((RenderObject child) {child.reassemble();});}/// 将 RenderObject 添加到 RenderObject tree 上@overridevoid attach(PipelineOwner owner) {assert(!_debugDisposed);super.attach(owner);if (_needsLayout && _relayoutBoundary != null) {// Don't enter this block if we've never laid out at all;// scheduleInitialLayout() will handle it_needsLayout = false;markNeedsLayout();}if (_needsCompositingBitsUpdate) {_needsCompositingBitsUpdate = false;markNeedsCompositingBitsUpdate();}if (_needsPaint && _layerHandle.layer != null) {// Don't enter this block if we've never painted at all;// scheduleInitialPaint() will handle it_needsPaint = false;markNeedsPaint();}if (_needsSemanticsUpdate && _semanticsConfiguration.isSemanticBoundary) {// Don't enter this block if we've never updated semantics at all;// scheduleInitialSemantics() will handle it_needsSemanticsUpdate = false;markNeedsSemanticsUpdate();}}/// 获取 约束@protectedConstraints get constraints {if (_constraints == null)throw StateError('A RenderObject does not have any constraints before it has been laid out.');return _constraints!;}/// 标记脏点,布局void markNeedsLayout() {assert(_debugCanPerformMutations);if (_needsLayout) {assert(_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout());return;}if (_relayoutBoundary == null) {_needsLayout = true;if (parent != null) {markParentNeedsLayout();}return;}if (_relayoutBoundary != this) {markParentNeedsLayout();} else {_needsLayout = true;if (owner != null) {assert(() {if (debugPrintMarkNeedsLayoutStacks)debugPrintStack(label: 'markNeedsLayout() called for $this');return true;}());owner!._nodesNeedingLayout.add(this);owner!.requestVisualUpdate();}}}// 合成void markNeedsCompositingBitsUpdate() {assert(!_debugDisposed);if (_needsCompositingBitsUpdate)return;_needsCompositingBitsUpdate = true;if (parent is RenderObject) {final RenderObject parent = this.parent! as RenderObject;if (parent._needsCompositingBitsUpdate)return;if (!isRepaintBoundary && !parent.isRepaintBoundary) {parent.markNeedsCompositingBitsUpdate();return;}}assert(() {final AbstractNode? parent = this.parent;if (parent is RenderObject)return parent._needsCompositing;return true;}());// parent is fine (or there isn't one), but we are dirtyif (owner != null)owner!._nodesNeedingCompositingBitsUpdate.add(this);}/// 绘制void markNeedsPaint() {assert(!_debugDisposed);assert(owner == null || !owner!.debugDoingPaint);if (_needsPaint)return;_needsPaint = true;if (isRepaintBoundary) {assert(() {if (debugPrintMarkNeedsPaintStacks)debugPrintStack(label: 'markNeedsPaint() called for $this');return true;}());// If we always have our own layer, then we can just repaint// ourselves without involving any other nodes.assert(_layerHandle.layer is OffsetLayer);if (owner != null) {owner!._nodesNeedingPaint.add(this);owner!.requestVisualUpdate();}} else if (parent is RenderObject) {final RenderObject parent = this.parent! as RenderObject;parent.markNeedsPaint();assert(parent == this.parent);} else {assert(() {if (debugPrintMarkNeedsPaintStacks)debugPrintStack(label: 'markNeedsPaint() called for $this (root of render tree)');return true;}());if (owner != null)owner!.requestVisualUpdate();}}}
根据 RenderObject 的 markNeedsLayout 、markNeedsCompositingBitsUpdate 、markNeedsPaint 得出 isRepaintBoundary 就是判断是否继续寻找父级,为 false,则向上寻找父级,直到 isRepaintBoundary = true 为止 。
RenderObjectWidget 源码分析
abstract class RenderObjectWidget extends Widget {const RenderObjectWidget({ super.key });@override@factoryRenderObjectElement createElement();@protected@factoryRenderObject createRenderObject(BuildContext context);@protectedvoid updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }@protectedvoid didUnmountRenderObject(covariant RenderObject renderObject) { }}
RenderObjectWidget 是 RenderObjectElement 的配置信息,操作 RenderObject 在 RenderObject tree 上的更新以及 取消挂载 。
RenderObjectElement 源码分析
abstract class RenderObjectElement extends Element {/// Creates an element that uses the given widget as its configuration.RenderObjectElement(RenderObjectWidget super.widget);/// The underlying [RenderObject] for this element.////// If this element has been [unmount]ed, this getter will throw.@overrideRenderObject get renderObject {assert(_renderObject != null, '$runtimeType unmounted');return _renderObject!;}RenderObject? _renderObject;bool _debugDoingBuild = false;@overridebool get debugDoingBuild => _debugDoingBuild;RenderObjectElement? _ancestorRenderObjectElement;RenderObjectElement? _findAncestorRenderObjectElement() {Element? ancestor = _parent;while (ancestor != null && ancestor is! RenderObjectElement)ancestor = ancestor._parent;return ancestor as RenderObjectElement?;}ParentDataElement<ParentData>? _findAncestorParentDataElement() {Element? ancestor = _parent;ParentDataElement<ParentData>? result;while (ancestor != null && ancestor is! RenderObjectElement) {if (ancestor is ParentDataElement<ParentData>) {result = ancestor;break;}ancestor = ancestor._parent;}assert(() {if (result == null || ancestor == null) {return true;}// Check that no other ParentDataWidgets want to provide parent data.final List<ParentDataElement<ParentData>> badAncestors = <ParentDataElement<ParentData>>[];ancestor = ancestor!._parent;while (ancestor != null && ancestor is! RenderObjectElement) {if (ancestor is ParentDataElement<ParentData>) {badAncestors.add(ancestor! as ParentDataElement<ParentData>);}ancestor = ancestor!._parent;}if (badAncestors.isNotEmpty) {badAncestors.insert(0, result);try {// We explicitly throw here (even though we immediately redirect the// exception elsewhere) so that debuggers will notice it when they// have "break on exception" enabled.throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('Incorrect use of ParentDataWidget.'),ErrorDescription('The following ParentDataWidgets are providing parent data to the same RenderObject:'),for (final ParentDataElement<ParentData> ancestor in badAncestors)ErrorDescription('- ${ancestor.widget} (typically placed directly inside a ${(ancestor.widget as ParentDataWidget<ParentData>).debugTypicalAncestorWidgetClass} widget)'),ErrorDescription('However, a RenderObject can only receive parent data from at most one ParentDataWidget.'),ErrorHint('Usually, this indicates that at least one of the offending ParentDataWidgets listed above is not placed directly inside a compatible ancestor widget.'),ErrorDescription('The ownership chain for the RenderObject that received the parent data was:\n ${debugGetCreatorChain(10)}'),]);} on FlutterError catch (e) {_debugReportException(ErrorSummary('while looking for parent data.'), e, e.stackTrace);}}return true;}());return result;}@overridevoid mount(Element? parent, Object? newSlot) {super.mount(parent, newSlot);assert(() {_debugDoingBuild = true;return true;}());_renderObject = (widget as RenderObjectWidget).createRenderObject(this);assert(!_renderObject!.debugDisposed!);assert(() {_debugDoingBuild = false;return true;}());assert(() {_debugUpdateRenderObjectOwner();return true;}());assert(_slot == newSlot);attachRenderObject(newSlot);_dirty = false;}@overridevoid update(covariant RenderObjectWidget newWidget) {super.update(newWidget);assert(widget == newWidget);assert(() {_debugUpdateRenderObjectOwner();return true;}());_performRebuild(); // calls widget.updateRenderObject()}void _debugUpdateRenderObjectOwner() {assert(() {renderObject.debugCreator = DebugCreator(this);return true;}());}@overridevoid performRebuild() {_performRebuild(); // calls widget.updateRenderObject()}@pragma('vm:prefer-inline')void _performRebuild() {assert(() {_debugDoingBuild = true;return true;}());(widget as RenderObjectWidget).updateRenderObject(this, renderObject);assert(() {_debugDoingBuild = false;return true;}());_dirty = false;}@protectedList<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element>? forgottenChildren, List<Object?>? slots }) {assert(oldChildren != null);assert(newWidgets != null);assert(slots == null || newWidgets.length == slots.length);Element? replaceWithNullIfForgotten(Element child) {return forgottenChildren != null && forgottenChildren.contains(child) ? null : child;}Object? slotFor(int newChildIndex, Element? previousChild) {return slots != null? slots[newChildIndex]: IndexedSlot<Element?>(newChildIndex, previousChild);}int newChildrenTop = 0;int oldChildrenTop = 0;int newChildrenBottom = newWidgets.length - 1;int oldChildrenBottom = oldChildren.length - 1;final List<Element> newChildren = oldChildren.length == newWidgets.length ?oldChildren : List<Element>.filled(newWidgets.length, _NullElement.instance);Element? previousChild;// Update the top of the list.while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);final Widget newWidget = newWidgets[newChildrenTop];assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))break;final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;assert(newChild._lifecycleState == _ElementLifecycle.active);newChildren[newChildrenTop] = newChild;previousChild = newChild;newChildrenTop += 1;oldChildrenTop += 1;}// Scan the bottom of the list.while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);final Widget newWidget = newWidgets[newChildrenBottom];assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))break;oldChildrenBottom -= 1;newChildrenBottom -= 1;}// Scan the old children in the middle of the list.final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;Map<Key, Element>? oldKeyedChildren;if (haveOldChildren) {oldKeyedChildren = <Key, Element>{};while (oldChildrenTop <= oldChildrenBottom) {final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);if (oldChild != null) {if (oldChild.widget.key != null)oldKeyedChildren[oldChild.widget.key!] = oldChild;elsedeactivateChild(oldChild);}oldChildrenTop += 1;}}// Update the middle of the list.while (newChildrenTop <= newChildrenBottom) {Element? oldChild;final Widget newWidget = newWidgets[newChildrenTop];if (haveOldChildren) {final Key? key = newWidget.key;if (key != null) {oldChild = oldKeyedChildren![key];if (oldChild != null) {if (Widget.canUpdate(oldChild.widget, newWidget)) {// we found a match!// remove it from oldKeyedChildren so we don't unsync it lateroldKeyedChildren.remove(key);} else {// Not a match, let's pretend we didn't see it for now.oldChild = null;}}}}assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;assert(newChild._lifecycleState == _ElementLifecycle.active);assert(oldChild == newChild || oldChild == null || oldChild._lifecycleState != _ElementLifecycle.active);newChildren[newChildrenTop] = newChild;previousChild = newChild;newChildrenTop += 1;}// We've scanned the whole list.assert(oldChildrenTop == oldChildrenBottom + 1);assert(newChildrenTop == newChildrenBottom + 1);assert(newWidgets.length - newChildrenTop == oldChildren.length - oldChildrenTop);newChildrenBottom = newWidgets.length - 1;oldChildrenBottom = oldChildren.length - 1;// Update the bottom of the list.while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {final Element oldChild = oldChildren[oldChildrenTop];assert(replaceWithNullIfForgotten(oldChild) != null);assert(oldChild._lifecycleState == _ElementLifecycle.active);final Widget newWidget = newWidgets[newChildrenTop];assert(Widget.canUpdate(oldChild.widget, newWidget));final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;assert(newChild._lifecycleState == _ElementLifecycle.active);assert(oldChild == newChild || oldChild == null || oldChild._lifecycleState != _ElementLifecycle.active);newChildren[newChildrenTop] = newChild;previousChild = newChild;newChildrenTop += 1;oldChildrenTop += 1;}// Clean up any of the remaining middle nodes from the old list.if (haveOldChildren && oldKeyedChildren!.isNotEmpty) {for (final Element oldChild in oldKeyedChildren.values) {if (forgottenChildren == null || !forgottenChildren.contains(oldChild))deactivateChild(oldChild);}}assert(newChildren.every((Element element) => element is! _NullElement));return newChildren;}@overridevoid deactivate() {super.deactivate();assert(!renderObject.attached,'A RenderObject was still attached when attempting to deactivate its ''RenderObjectElement: $renderObject',);}@overridevoid unmount() {assert(!renderObject.debugDisposed!,'A RenderObject was disposed prior to its owning element being unmounted: ''$renderObject',);final RenderObjectWidget oldWidget = widget as RenderObjectWidget;super.unmount();assert(!renderObject.attached,'A RenderObject was still attached when attempting to unmount its ''RenderObjectElement: $renderObject',);oldWidget.didUnmountRenderObject(renderObject);_renderObject!.dispose();_renderObject = null;}void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) {bool applyParentData = true;assert(() {try {if (!parentDataWidget.debugIsValidRenderObject(renderObject)) {applyParentData = false;throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('Incorrect use of ParentDataWidget.'),...parentDataWidget._debugDescribeIncorrectParentDataType(parentData: renderObject.parentData,parentDataCreator: _ancestorRenderObjectElement!.widget as RenderObjectWidget,ownershipChain: ErrorDescription(debugGetCreatorChain(10)),),]);}} on FlutterError catch (e) {_debugReportException(ErrorSummary('while applying parent data.'), e, e.stackTrace);}return true;}());if (applyParentData)parentDataWidget.applyParentData(renderObject);}@overridevoid _updateSlot(Object? newSlot) {final Object? oldSlot = slot;assert(oldSlot != newSlot);super._updateSlot(newSlot);assert(slot == newSlot);_ancestorRenderObjectElement!.moveRenderObjectChild(renderObject, oldSlot, slot);}@overridevoid attachRenderObject(Object? newSlot) {assert(_ancestorRenderObjectElement == null);_slot = newSlot;_ancestorRenderObjectElement = _findAncestorRenderObjectElement();_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);final ParentDataElement<ParentData>? parentDataElement = _findAncestorParentDataElement();if (parentDataElement != null)_updateParentData(parentDataElement.widget as ParentDataWidget<ParentData>);}@overridevoid detachRenderObject() {if (_ancestorRenderObjectElement != null) {_ancestorRenderObjectElement!.removeRenderObjectChild(renderObject, slot);_ancestorRenderObjectElement = null;}_slot = null;}@protectedvoid insertRenderObjectChild(covariant RenderObject child, covariant Object? slot) {assert(() {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('RenderObjectElement.insertChildRenderObject() is deprecated.'),toDiagnosticsNode(name: 'insertChildRenderObject() was called on this Element',style: DiagnosticsTreeStyle.shallow,),ErrorDescription('insertChildRenderObject() has been deprecated in favor of ''insertRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 ''for details.',),ErrorHint('Rather than overriding insertChildRenderObject() in your ''RenderObjectElement subclass, override insertRenderObjectChild() instead, '"and DON'T call super.insertRenderObjectChild(). If you're implementing a "'new RenderObjectElement, you should override/implement ''insertRenderObjectChild(), moveRenderObjectChild(), and ''removeRenderObjectChild().',),]);}());}@protectedvoid moveRenderObjectChild(covariant RenderObject child, covariant Object? oldSlot, covariant Object? newSlot) {assert(() {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('RenderObjectElement.moveChildRenderObject() is deprecated.'),toDiagnosticsNode(name: 'super.moveChildRenderObject() was called on this Element',style: DiagnosticsTreeStyle.shallow,),ErrorDescription('moveChildRenderObject() has been deprecated in favor of ''moveRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 ''for details.',),ErrorHint('Rather than overriding moveChildRenderObject() in your ''RenderObjectElement subclass, override moveRenderObjectChild() instead, '"and DON'T call super.moveRenderObjectChild(). If you're implementing a "'new RenderObjectElement, you should override/implement ''insertRenderObjectChild(), moveRenderObjectChild(), and ''removeRenderObjectChild().',),]);}());}/// Remove the given child from [renderObject].////// The given child is guaranteed to have been inserted at the given `slot`/// and have [renderObject] as its parent.@protectedvoid removeRenderObjectChild(covariant RenderObject child, covariant Object? slot) {assert(() {throw FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('RenderObjectElement.removeChildRenderObject() is deprecated.'),toDiagnosticsNode(name: 'super.removeChildRenderObject() was called on this Element',style: DiagnosticsTreeStyle.shallow,),ErrorDescription('removeChildRenderObject() has been deprecated in favor of ''removeRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 ''for details.',),ErrorHint('Rather than overriding removeChildRenderObject() in your ''RenderObjectElement subclass, override removeRenderObjectChild() instead, '"and DON'T call super.removeRenderObjectChild(). If you're implementing a "'new RenderObjectElement, you should override/implement ''insertRenderObjectChild(), moveRenderObjectChild(), and ''removeRenderObjectChild().',),]);}());}@overridevoid debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.add(DiagnosticsProperty<RenderObject>('renderObject', _renderObject, defaultValue: null));}}
RenderObjectElement 维护 Element 的新旧 slot 的值,以及位置,其方法会触发 RenderObject 在 RenderObject tree上的 slot 改变。
三者之间的流程图

