Widget 源码分析

  1. abstract class Widget extends DiagnosticableTree {
  2. const Widget({ this.key });
  3. final Key? key;
  4. @protected
  5. @factory
  6. Element createElement();
  7. @override
  8. String toStringShort() {
  9. final String type = objectRuntimeType(this, 'Widget');
  10. return key == null ? type : '$type-$key';
  11. }
  12. @override
  13. void debugFillProperties(DiagnosticPropertiesBuilder properties) {
  14. super.debugFillProperties(properties);
  15. properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  16. }
  17. @override
  18. @nonVirtual
  19. bool operator ==(Object other) => super == other;
  20. @override
  21. @nonVirtual
  22. int get hashCode => super.hashCode;
  23. static bool canUpdate(Widget oldWidget, Widget newWidget) {
  24. return oldWidget.runtimeType == newWidget.runtimeType
  25. && oldWidget.key == newWidget.key;
  26. }
  27. // 返回特定 `Widget` 具体子类型的数字编码。
  28. // 这在 `Element.updateChild` 中用于确定热重载是否修改了
  29. // 已安装元素配置的超类。 每个 `Widget` 的编码
  30. // 必须匹配 `Element._debugConcreteSubtype` 中对应的 `Element` 编码。
  31. static int _debugConcreteSubtype(Widget widget) {
  32. return widget is StatefulWidget ? 1 :
  33. widget is StatelessWidget ? 2 :
  34. 0;
  35. }
  36. }

这里 Widget 会创建对应 的 Element,StatelessWidget 会创建 StatelessElement 类型的 Element,而 StatefulWidget 会创建 StatefulElement 类型的 Element。

  1. abstract class StatelessWidget extends Widget {
  2. const StatelessWidget({ super.key });
  3. @override
  4. StatelessElement createElement() => StatelessElement(this);
  5. @protected
  6. Widget build(BuildContext context);
  7. }
  1. abstract class StatefulWidget extends Widget {
  2. const StatefulWidget({ super.key });
  3. @override
  4. StatefulElement createElement() => StatefulElement(this);
  5. @protected
  6. @factory
  7. State createState();
  8. }

从这里可以看出有 状态组件 和 无状态 组件就差别在于是否有配置信息。

State 源码分析

  1. abstract class State<T extends StatefulWidget> with Diagnosticable {
  2. T get widget => _widget!;
  3. T? _widget;
  4. /// 此状态对象的生命周期中的当前阶段。
  5. _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
  6. /// 为那个特定的 [Widget] 创建。
  7. bool _debugTypesAreRight(Widget widget) => widget is T;
  8. /// 当前 Widget 在树中所在的位置
  9. BuildContext get context {
  10. assert(() {
  11. if (_element == null) {
  12. throw FlutterError(
  13. 'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
  14. 'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
  15. );
  16. }
  17. return true;
  18. }());
  19. return _element!;
  20. }
  21. StatefulElement? _element;
  22. // 当前 Widget 是否被挂载到树上
  23. bool get mounted => _element != null;
  24. /// 当这个对象被插入到树中时调用。
  25. /// 将为每个 [State] 对象仅调用一次此方法
  26. @protected
  27. @mustCallSuper
  28. void initState() {
  29. assert(_debugLifecycleState == _StateLifecycle.created);
  30. }
  31. /// 当 此对象 配置发生变化时调用
  32. @mustCallSuper
  33. @protected
  34. void didUpdateWidget(covariant T oldWidget) { }
  35. /// 调用此方法将 调用 build 方法 ;reassemble 方法并不需要做些什么
  36. @protected
  37. @mustCallSuper
  38. void reassemble() { }
  39. /// 通知框架这个对象的内部状态已经改变。
  40. /// 调用 此方法可能会影响用户界面
  41. /// 子树也会因此父 Widget 调用 SetState 而 build
  42. @protected
  43. void setState(VoidCallback fn) {
  44. assert(fn != null);
  45. assert(() {
  46. if (_debugLifecycleState == _StateLifecycle.defunct) {
  47. throw FlutterError.fromParts(<DiagnosticsNode>[
  48. ErrorSummary('setState() called after dispose(): $this'),
  49. ErrorDescription(
  50. 'This error happens if you call setState() on a State object for a widget that '
  51. 'no longer appears in the widget tree (e.g., whose parent widget no longer '
  52. 'includes the widget in its build). This error can occur when code calls '
  53. 'setState() from a timer or an animation callback.',
  54. ),
  55. ErrorHint(
  56. 'The preferred solution is '
  57. 'to cancel the timer or stop listening to the animation in the dispose() '
  58. 'callback. Another solution is to check the "mounted" property of this '
  59. 'object before calling setState() to ensure the object is still in the '
  60. 'tree.',
  61. ),
  62. ErrorHint(
  63. 'This error might indicate a memory leak if setState() is being called '
  64. 'because another object is retaining a reference to this State object '
  65. 'after it has been removed from the tree. To avoid memory leaks, '
  66. 'consider breaking the reference to this object during dispose().',
  67. ),
  68. ]);
  69. }
  70. if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
  71. throw FlutterError.fromParts(<DiagnosticsNode>[
  72. ErrorSummary('setState() called in constructor: $this'),
  73. ErrorHint(
  74. 'This happens when you call setState() on a State object for a widget that '
  75. "hasn't been inserted into the widget tree yet. It is not necessary to call "
  76. 'setState() in the constructor, since the state is already assumed to be dirty '
  77. 'when it is initially created.',
  78. ),
  79. ]);
  80. }
  81. return true;
  82. }());
  83. final Object? result = fn() as dynamic;
  84. assert(() {
  85. if (result is Future) {
  86. throw FlutterError.fromParts(<DiagnosticsNode>[
  87. ErrorSummary('setState() callback argument returned a Future.'),
  88. ErrorDescription(
  89. 'The setState() method on $this was called with a closure or method that '
  90. 'returned a Future. Maybe it is marked as "async".',
  91. ),
  92. ErrorHint(
  93. 'Instead of performing asynchronous work inside a call to setState(), first '
  94. 'execute the work (without updating the widget state), and then synchronously '
  95. 'update the state inside a call to setState().',
  96. ),
  97. ]);
  98. }
  99. return true;
  100. }());
  101. _element!.markNeedsBuild();
  102. }
  103. /// 当这个对象从树中移除时调用。
  104. @protected
  105. @mustCallSuper
  106. void deactivate() { }
  107. /// 当这个对象被重新插入到树中时调用
  108. @protected
  109. @mustCallSuper
  110. void activate() { }
  111. /// 当此对象从树中永久删除时调用。
  112. @protected
  113. @mustCallSuper
  114. void dispose() {
  115. assert(_debugLifecycleState == _StateLifecycle.ready);
  116. assert(() {
  117. _debugLifecycleState = _StateLifecycle.defunct;
  118. return true;
  119. }());
  120. }
  121. /// 描述这个小部件所代表的用户界面部分。
  122. @protected
  123. Widget build(BuildContext context);
  124. /// 当此 [State] 对象的依赖项发生更改时调用。
  125. /// 在 initState() 后,调用
  126. @protected
  127. @mustCallSuper
  128. void didChangeDependencies() { }
  129. @override
  130. void debugFillProperties(DiagnosticPropertiesBuilder properties) {
  131. super.debugFillProperties(properties);
  132. assert(() {
  133. properties.add(EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));
  134. return true;
  135. }());
  136. properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
  137. properties.add(ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));
  138. }
  139. }

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] 对象。

  1. abstract class BuildContext {
  2. /// The current configuration of the [Element] that is this [BuildContext].
  3. Widget get widget;
  4. /// 管理此上下文的渲染管道。
  5. BuildOwner? get owner;
  6. /// 当前是否正在更新 Widget 或 渲染树
  7. bool get debugDoingBuild;
  8. /// Widget 的当前 [RenderObject]
  9. RenderObject? findRenderObject();
  10. /// [findRenderObject] 返回的 [RenderBox] 的大小。
  11. Size? get size;
  12. /// 用 [ancestor] 注册这个构建上下文
  13. InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
  14. /// 获取给定类型`T`的最近的 Widget ,它必须是a的类型
  15. /// 具体的 [InheritedWidget] 子类,并将此构建上下文注册到
  16. /// 该 Widget 使得当该 Widget 更改时(或该 Widget 的新 Widget
  17. /// 类型被引入,或者 Widget 消失),这个构建上下文是
  18. /// 重建,以便它可以从该 Widget 获取新值。
  19. T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect });
  20. /// 获取与给定类型`T`最近的 Widget 对应的 Element,
  21. /// 必须是具体的 [InheritedWidget] 子类的类型。
  22. /// 如果没有找到这样的 Element,则返回 null。
  23. InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
  24. /// 返回给定类型`T`的最近的祖先小部件,它必须是
  25. /// 具体 [Widget] 子类的类型。
  26. T? findAncestorWidgetOfExactType<T extends Widget>();
  27. /// 返回最近的祖先 [StatefulWidget] 小部件的 [State] 对象
  28. /// 这是给定类型 `T` 的一个实例。
  29. T? findAncestorStateOfType<T extends State>();
  30. /// 返回最远祖先 [StatefulWidget] 小部件的 [State] 对象
  31. /// 这是给定类型 `T` 的一个实例。
  32. T? findRootAncestorStateOfType<T extends State>();
  33. /// 返回最近的祖先 [RenderObjectWidget] Widget 的 [RenderObject] 对象
  34. /// 这是给定类型 `T` 的一个实例。
  35. T? findAncestorRenderObjectOfType<T extends RenderObject>();
  36. /// 遍历祖先链,从这个构建上下文的父节点开始
  37. /// 回调被赋予一个对祖先 Widget 对应的 [Element] 对象的引用。
  38. void visitAncestorElements(bool Function(Element element) visitor);
  39. /// 遍历这个 Widget 的子节点。
  40. void visitChildElements(ElementVisitor visitor);
  41. /// 在给定的构建上下文中开始冒泡这个通知。
  42. void dispatchNotification(Notification notification);
  43. /// 返回与当前构建 context 关联的 [Element] 的描述。
  44. DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});
  45. /// 返回与当前构建 context 关联的 [Widget] 的描述。
  46. DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});
  47. /// 添加当前缺少的特定类型小部件的描述
  48. List<DiagnosticsNode> describeMissingAncestor({ required Type expectedAncestorType });
  49. /// 从特定的 [Element] 添加所有权链的描述
  50. DiagnosticsNode describeOwnershipChain(String name);
  51. }
  1. /// 节选代码
  2. abstract class Element extends DiagnosticableTree implements BuildContext {
  3. /// 此 Element 的配置。
  4. @override
  5. Widget get widget => _widget!;
  6. Widget? _widget;
  7. /// 管理此 Element 生命周期的对象。
  8. @override
  9. BuildOwner? get owner => _owner;
  10. BuildOwner? _owner;
  11. /// 树中此位置(或下方)的 renderObject。
  12. RenderObject? get renderObject {
  13. RenderObject? result;
  14. void visit(Element element) {
  15. assert(result == null); // this verifies that there's only one child
  16. if (element._lifecycleState == _ElementLifecycle.defunct) {
  17. return;
  18. } else if (element is RenderObjectElement) {
  19. result = element.renderObject;
  20. } else {
  21. element.visitChildren(visit);
  22. }
  23. }
  24. visit(this);
  25. return result;
  26. }
  27. /// 使用给定的新配置更新给定的子节点。
  28. Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
  29. if (newWidget == null) {
  30. if (child != null)
  31. deactivateChild(child);
  32. return null;
  33. }
  34. final Element newChild;
  35. if (child != null) {
  36. bool hasSameSuperclass = true;
  37. assert(() {
  38. final int oldElementClass = Element._debugConcreteSubtype(child);
  39. final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
  40. hasSameSuperclass = oldElementClass == newWidgetClass;
  41. return true;
  42. }());
  43. if (hasSameSuperclass && child.widget == newWidget) {
  44. if (child.slot != newSlot)
  45. updateSlotForChild(child, newSlot);
  46. newChild = child;
  47. } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
  48. if (child.slot != newSlot)
  49. updateSlotForChild(child, newSlot);
  50. final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
  51. if (isTimelineTracked) {
  52. Map<String, String>? debugTimelineArguments;
  53. assert(() {
  54. if (kDebugMode && debugEnhanceBuildTimelineArguments) {
  55. debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
  56. }
  57. return true;
  58. }());
  59. Timeline.startSync(
  60. '${newWidget.runtimeType}',
  61. arguments: debugTimelineArguments,
  62. );
  63. }
  64. child.update(newWidget);
  65. if (isTimelineTracked)
  66. Timeline.finishSync();
  67. assert(child.widget == newWidget);
  68. assert(() {
  69. child.owner!._debugElementWasRebuilt(child);
  70. return true;
  71. }());
  72. newChild = child;
  73. } else {
  74. deactivateChild(child);
  75. assert(child._parent == null);
  76. newChild = inflateWidget(newWidget, newSlot);
  77. }
  78. } else {
  79. newChild = inflateWidget(newWidget, newSlot);
  80. }
  81. assert(() {
  82. if (child != null)
  83. _debugRemoveGlobalKeyReservation(child);
  84. final Key? key = newWidget.key;
  85. if (key is GlobalKey) {
  86. assert(owner != null);
  87. owner!._debugReserveGlobalKeyFor(this, newChild, key);
  88. }
  89. return true;
  90. }());
  91. return newChild;
  92. }
  93. /// 将此元素添加到给定父级的给定槽中的树中。
  94. void mount(Element? parent, Object? newSlot) {
  95. assert(_lifecycleState == _ElementLifecycle.initial);
  96. assert(widget != null);
  97. assert(_parent == null);
  98. assert(parent == null || parent._lifecycleState == _ElementLifecycle.active);
  99. assert(slot == null);
  100. _parent = parent;
  101. _slot = newSlot;
  102. _lifecycleState = _ElementLifecycle.active;
  103. _depth = _parent != null ? _parent!.depth + 1 : 1;
  104. if (parent != null) {
  105. _owner = parent.owner;
  106. }
  107. assert(owner != null);
  108. final Key? key = widget.key;
  109. if (key is GlobalKey) {
  110. owner!._registerGlobalKey(key, this);
  111. }
  112. _updateInheritance();
  113. attachNotificationTree();
  114. }
  115. /// 更改用于配置此 Element 的 Widget。
  116. @mustCallSuper
  117. void update(covariant Widget newWidget) {
  118. assert(
  119. _lifecycleState == _ElementLifecycle.active
  120. && widget != null
  121. && newWidget != null
  122. && newWidget != widget
  123. && depth != null
  124. && Widget.canUpdate(widget, newWidget),
  125. );
  126. assert(() {
  127. _debugForgottenChildrenWithGlobalKey?.forEach(_debugRemoveGlobalKeyReservation);
  128. _debugForgottenChildrenWithGlobalKey?.clear();
  129. return true;
  130. }());
  131. _widget = newWidget;
  132. }
  133. /// 将 [renderObject] 添加到render tree中 `newSlot` 指定的位置。
  134. void attachRenderObject(Object? newSlot) {
  135. assert(_slot == null);
  136. visitChildren((Element child) {
  137. child.attachRenderObject(newSlot);
  138. });
  139. _slot = newSlot;
  140. }
  141. /// 从渲染树中移除 [renderObject]。
  142. void detachRenderObject() {
  143. visitChildren((Element child) {
  144. child.detachRenderObject();
  145. });
  146. _slot = null;
  147. }
  148. /// 返回 与此 Element 对应的 renderObject
  149. RenderObject? findRenderObject() {
  150. assert(() {
  151. if (_lifecycleState != _ElementLifecycle.active) {
  152. throw FlutterError.fromParts(<DiagnosticsNode>[
  153. ErrorSummary('Cannot get renderObject of inactive element.'),
  154. ErrorDescription(
  155. 'In order for an element to have a valid renderObject, it must be '
  156. 'active, which means it is part of the tree.\n'
  157. 'Instead, this element is in the $_lifecycleState state.\n'
  158. 'If you called this method from a State object, consider guarding '
  159. 'it with State.mounted.',
  160. ),
  161. describeElement('The findRenderObject() method was called for the following element'),
  162. ]);
  163. }
  164. return true;
  165. }());
  166. return renderObject;
  167. }
  168. /// 当这个 Element 的依赖改变时调用。
  169. @mustCallSuper
  170. void didChangeDependencies() {
  171. assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
  172. assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
  173. markNeedsBuild();
  174. }
  175. /// 将元素标记为脏并将其添加到 Widget 的全局列表中
  176. /// 在下一帧重建。
  177. void markNeedsBuild() {
  178. assert(_lifecycleState != _ElementLifecycle.defunct);
  179. if (_lifecycleState != _ElementLifecycle.active)
  180. return;
  181. assert(owner != null);
  182. assert(_lifecycleState == _ElementLifecycle.active);
  183. assert(() {
  184. if (owner!._debugBuilding) {
  185. assert(owner!._debugCurrentBuildTarget != null);
  186. assert(owner!._debugStateLocked);
  187. if (_debugIsInScope(owner!._debugCurrentBuildTarget!))
  188. return true;
  189. if (!_debugAllowIgnoredCallsToMarkNeedsBuild) {
  190. final List<DiagnosticsNode> information = <DiagnosticsNode>[
  191. ErrorSummary('setState() or markNeedsBuild() called during build.'),
  192. ErrorDescription(
  193. 'This ${widget.runtimeType} widget cannot be marked as needing to build because the framework '
  194. 'is already in the process of building widgets. A widget can be marked as '
  195. 'needing to be built during the build phase only if one of its ancestors '
  196. 'is currently building. This exception is allowed because the framework '
  197. 'builds parent widgets before children, which means a dirty descendant '
  198. 'will always be built. Otherwise, the framework might not visit this '
  199. 'widget during this build phase.',
  200. ),
  201. describeElement('The widget on which setState() or markNeedsBuild() was called was'),
  202. ];
  203. if (owner!._debugCurrentBuildTarget != null)
  204. information.add(owner!._debugCurrentBuildTarget!.describeWidget('The widget which was currently being built when the offending call was made was'));
  205. throw FlutterError.fromParts(information);
  206. }
  207. 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)
  208. } else if (owner!._debugStateLocked) {
  209. assert(!_debugAllowIgnoredCallsToMarkNeedsBuild);
  210. throw FlutterError.fromParts(<DiagnosticsNode>[
  211. ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),
  212. ErrorDescription(
  213. 'This ${widget.runtimeType} widget cannot be marked as needing to build '
  214. 'because the framework is locked.',
  215. ),
  216. describeElement('The widget on which setState() or markNeedsBuild() was called was'),
  217. ]);
  218. }
  219. return true;
  220. }());
  221. if (dirty)
  222. return;
  223. _dirty = true;
  224. owner!.scheduleBuildFor(this);
  225. }
  226. /// 使 Widget 自行更新。
  227. void rebuild() {
  228. assert(_lifecycleState != _ElementLifecycle.initial);
  229. if (_lifecycleState != _ElementLifecycle.active || !_dirty)
  230. return;
  231. assert(() {
  232. debugOnRebuildDirtyWidget?.call(this, _debugBuiltOnce);
  233. if (debugPrintRebuildDirtyWidgets) {
  234. if (!_debugBuiltOnce) {
  235. debugPrint('Building $this');
  236. _debugBuiltOnce = true;
  237. } else {
  238. debugPrint('Rebuilding $this');
  239. }
  240. }
  241. return true;
  242. }());
  243. assert(_lifecycleState == _ElementLifecycle.active);
  244. assert(owner!._debugStateLocked);
  245. Element? debugPreviousBuildTarget;
  246. assert(() {
  247. debugPreviousBuildTarget = owner!._debugCurrentBuildTarget;
  248. owner!._debugCurrentBuildTarget = this;
  249. return true;
  250. }());
  251. performRebuild();
  252. assert(() {
  253. assert(owner!._debugCurrentBuildTarget == this);
  254. owner!._debugCurrentBuildTarget = debugPreviousBuildTarget;
  255. return true;
  256. }());
  257. assert(!_dirty);
  258. }
  259. /// 检测是否更新Element
  260. @protected
  261. @pragma('vm:prefer-inline')
  262. Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
  263. if (newWidget == null) {
  264. if (child != null)
  265. deactivateChild(child);
  266. return null;
  267. }
  268. final Element newChild;
  269. if (child != null) {
  270. bool hasSameSuperclass = true;
  271. assert(() {
  272. final int oldElementClass = Element._debugConcreteSubtype(child);
  273. final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
  274. hasSameSuperclass = oldElementClass == newWidgetClass;
  275. return true;
  276. }());
  277. if (hasSameSuperclass && child.widget == newWidget) {
  278. if (child.slot != newSlot)
  279. updateSlotForChild(child, newSlot);
  280. newChild = child;
  281. } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
  282. if (child.slot != newSlot)
  283. updateSlotForChild(child, newSlot);
  284. final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
  285. if (isTimelineTracked) {
  286. Map<String, String>? debugTimelineArguments;
  287. assert(() {
  288. if (kDebugMode && debugEnhanceBuildTimelineArguments) {
  289. debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
  290. }
  291. return true;
  292. }());
  293. Timeline.startSync(
  294. '${newWidget.runtimeType}',
  295. arguments: debugTimelineArguments,
  296. );
  297. }
  298. child.update(newWidget);
  299. if (isTimelineTracked)
  300. Timeline.finishSync();
  301. assert(child.widget == newWidget);
  302. assert(() {
  303. child.owner!._debugElementWasRebuilt(child);
  304. return true;
  305. }());
  306. newChild = child;
  307. } else {
  308. deactivateChild(child);
  309. assert(child._parent == null);
  310. newChild = inflateWidget(newWidget, newSlot);
  311. }
  312. } else {
  313. newChild = inflateWidget(newWidget, newSlot);
  314. }
  315. assert(() {
  316. if (child != null)
  317. _debugRemoveGlobalKeyReservation(child);
  318. final Key? key = newWidget.key;
  319. if (key is GlobalKey) {
  320. assert(owner != null);
  321. owner!._debugReserveGlobalKeyFor(this, newChild, key);
  322. }
  323. return true;
  324. }());
  325. return newChild;
  326. }
  327. }

当前 Element 所依赖的配置 发生变化时,会把当前 Element 的 _dirty 标致为 true ,加入待渲染管道,在下一帧渲染。

StatelessElement 源码分析

  1. class StatelessElement extends ComponentElement {
  2. StatelessElement(StatelessWidget super.widget);
  3. @override
  4. Widget build() => (widget as StatelessWidget).build(this);
  5. @override
  6. void update(StatelessWidget newWidget) {
  7. super.update(newWidget);
  8. assert(widget == newWidget);
  9. _dirty = true;
  10. rebuild();
  11. }
  12. }

根据 StatelessElement 源码得知,在 StatelessWidget 的配置信息发生变化时,当前 StatelessElement 的 脏点 会被标记为 true ,在下一帧会被重新刷新,以及刷新当前 Widget 的子组件。因此尽量在Widget tree中变化少的节点使用 StatelessWidget 。

StatefulElement 源码分析

  1. class StatefulElement extends ComponentElement {
  2. StatefulElement(StatefulWidget widget)
  3. : _state = widget.createState(),
  4. super(widget) {
  5. assert(() {
  6. if (!state._debugTypesAreRight(widget)) {
  7. throw FlutterError.fromParts(<DiagnosticsNode>[
  8. ErrorSummary('StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>'),
  9. ErrorDescription(
  10. 'The createState function for ${widget.runtimeType} returned a state '
  11. 'of type ${state.runtimeType}, which is not a subtype of '
  12. 'State<${widget.runtimeType}>, violating the contract for createState.',
  13. ),
  14. ]);
  15. }
  16. return true;
  17. }());
  18. assert(state._element == null);
  19. state._element = this;
  20. assert(
  21. state._widget == null,
  22. 'The createState function for $widget returned an old or invalid state '
  23. 'instance: ${state._widget}, which is not null, violating the contract '
  24. 'for createState.',
  25. );
  26. state._widget = widget;
  27. assert(state._debugLifecycleState == _StateLifecycle.created);
  28. }
  29. /// 创建 State
  30. @override
  31. Widget build() => state.build(this);
  32. /// The [State] instance associated with this location in the tree.
  33. ///
  34. /// There is a one-to-one relationship between [State] objects and the
  35. /// [StatefulElement] objects that hold them. The [State] objects are created
  36. /// by [StatefulElement] in [mount].
  37. State<StatefulWidget> get state => _state!;
  38. State<StatefulWidget>? _state;
  39. /// 热重载
  40. @override
  41. void reassemble() {
  42. if (_debugShouldReassemble(_debugReassembleConfig, _widget)) {
  43. state.reassemble();
  44. }
  45. super.reassemble();
  46. }
  47. @override
  48. void _firstBuild() {
  49. assert(state._debugLifecycleState == _StateLifecycle.created);
  50. try {
  51. _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
  52. final Object? debugCheckForReturnedFuture = state.initState() as dynamic;
  53. assert(() {
  54. if (debugCheckForReturnedFuture is Future) {
  55. throw FlutterError.fromParts(<DiagnosticsNode>[
  56. ErrorSummary('${state.runtimeType}.initState() returned a Future.'),
  57. ErrorDescription('State.initState() must be a void method without an `async` keyword.'),
  58. ErrorHint(
  59. 'Rather than awaiting on asynchronous work directly inside of initState, '
  60. 'call a separate method to do this work without awaiting it.',
  61. ),
  62. ]);
  63. }
  64. return true;
  65. }());
  66. } finally {
  67. _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
  68. }
  69. assert(() {
  70. state._debugLifecycleState = _StateLifecycle.initialized;
  71. return true;
  72. }());
  73. state.didChangeDependencies();
  74. assert(() {
  75. state._debugLifecycleState = _StateLifecycle.ready;
  76. return true;
  77. }());
  78. super._firstBuild();
  79. }
  80. /// 更改配置信息,重建 Element
  81. @override
  82. void performRebuild() {
  83. if (_didChangeDependencies) {
  84. state.didChangeDependencies();
  85. _didChangeDependencies = false;
  86. }
  87. super.performRebuild();
  88. }
  89. /// 更新 当前 Element
  90. @override
  91. void update(StatefulWidget newWidget) {
  92. super.update(newWidget);
  93. assert(widget == newWidget);
  94. final StatefulWidget oldWidget = state._widget!;
  95. _dirty = true;
  96. state._widget = widget as StatefulWidget;
  97. try {
  98. _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
  99. final Object? debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic;
  100. assert(() {
  101. if (debugCheckForReturnedFuture is Future) {
  102. throw FlutterError.fromParts(<DiagnosticsNode>[
  103. ErrorSummary('${state.runtimeType}.didUpdateWidget() returned a Future.'),
  104. ErrorDescription( 'State.didUpdateWidget() must be a void method without an `async` keyword.'),
  105. ErrorHint(
  106. 'Rather than awaiting on asynchronous work directly inside of didUpdateWidget, '
  107. 'call a separate method to do this work without awaiting it.',
  108. ),
  109. ]);
  110. }
  111. return true;
  112. }());
  113. } finally {
  114. _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
  115. }
  116. rebuild();
  117. }
  118. /// 激活 Element
  119. @override
  120. void activate() {
  121. super.activate();
  122. state.activate();
  123. // Since the State could have observed the deactivate() and thus disposed of
  124. // resources allocated in the build method, we have to rebuild the widget
  125. // so that its State can reallocate its resources.
  126. assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
  127. markNeedsBuild();
  128. }
  129. /// Element 消活
  130. @override
  131. void deactivate() {
  132. state.deactivate();
  133. super.deactivate();
  134. }
  135. /// 把 Element 从 tree 中取消挂载
  136. @override
  137. void unmount() {
  138. super.unmount();
  139. state.dispose();
  140. assert(() {
  141. if (state._debugLifecycleState == _StateLifecycle.defunct)
  142. return true;
  143. throw FlutterError.fromParts(<DiagnosticsNode>[
  144. ErrorSummary('${state.runtimeType}.dispose failed to call super.dispose.'),
  145. ErrorDescription(
  146. 'dispose() implementations must always call their superclass dispose() method, to ensure '
  147. 'that all the resources used by the widget are fully released.',
  148. ),
  149. ]);
  150. }());
  151. state._element = null;
  152. // Release resources to reduce the severity of memory leaks caused by
  153. // defunct, but accidentally retained Elements.
  154. _state = null;
  155. }
  156. @override
  157. InheritedWidget dependOnInheritedElement(Element ancestor, { Object? aspect }) {
  158. assert(ancestor != null);
  159. assert(() {
  160. final Type targetType = ancestor.widget.runtimeType;
  161. if (state._debugLifecycleState == _StateLifecycle.created) {
  162. throw FlutterError.fromParts(<DiagnosticsNode>[
  163. ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called before ${state.runtimeType}.initState() completed.'),
  164. ErrorDescription(
  165. 'When an inherited widget changes, for example if the value of Theme.of() changes, '
  166. "its dependent widgets are rebuilt. If the dependent widget's reference to "
  167. 'the inherited widget is in a constructor or an initState() method, '
  168. 'then the rebuilt dependent widget will not reflect the changes in the '
  169. 'inherited widget.',
  170. ),
  171. ErrorHint(
  172. 'Typically references to inherited widgets should occur in widget build() methods. Alternatively, '
  173. 'initialization based on inherited widgets can be placed in the didChangeDependencies method, which '
  174. 'is called after initState and whenever the dependencies change thereafter.',
  175. ),
  176. ]);
  177. }
  178. if (state._debugLifecycleState == _StateLifecycle.defunct) {
  179. throw FlutterError.fromParts(<DiagnosticsNode>[
  180. ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called after dispose(): $this'),
  181. ErrorDescription(
  182. 'This error happens if you call dependOnInheritedWidgetOfExactType() on the '
  183. 'BuildContext for a widget that no longer appears in the widget tree '
  184. '(e.g., whose parent widget no longer includes the widget in its '
  185. 'build). This error can occur when code calls '
  186. 'dependOnInheritedWidgetOfExactType() from a timer or an animation callback.',
  187. ),
  188. ErrorHint(
  189. 'The preferred solution is to cancel the timer or stop listening to the '
  190. 'animation in the dispose() callback. Another solution is to check the '
  191. '"mounted" property of this object before calling '
  192. 'dependOnInheritedWidgetOfExactType() to ensure the object is still in the '
  193. 'tree.',
  194. ),
  195. ErrorHint(
  196. 'This error might indicate a memory leak if '
  197. 'dependOnInheritedWidgetOfExactType() is being called because another object '
  198. 'is retaining a reference to this State object after it has been '
  199. 'removed from the tree. To avoid memory leaks, consider breaking the '
  200. 'reference to this object during dispose().',
  201. ),
  202. ]);
  203. }
  204. return true;
  205. }());
  206. return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
  207. }
  208. bool _didChangeDependencies = false;
  209. /// 复用 配置信息
  210. @override
  211. void didChangeDependencies() {
  212. super.didChangeDependencies();
  213. _didChangeDependencies = true;
  214. }
  215. @override
  216. DiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {
  217. return _ElementDiagnosticableTreeNode(
  218. name: name,
  219. value: this,
  220. style: style,
  221. stateful: true,
  222. );
  223. }
  224. @override
  225. void debugFillProperties(DiagnosticPropertiesBuilder properties) {
  226. super.debugFillProperties(properties);
  227. properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', _state, defaultValue: null));
  228. }
  229. }

StatefulElement 在 首次构建的时候,State.didChangeDependencies( )就被调用,以及在消活时,调用 state.deactivate( ),再被从Element tree 移除挂载时,调用 state.dispose( ),永久删除 Widget,释放资源。因此得出 StatefulWidget 的生命周期为 :
Widget 和 Element 、RenderObject之间的关系 - 图1


RenderObject 源码分析

  1. // 节选代码
  2. abstract class RenderObject extends AbstractNode with
  3. DiagnosticableTreeMixin implements HitTestTarget {
  4. RenderObject() {
  5. _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
  6. }
  7. /// 热重载
  8. void reassemble() {
  9. markNeedsLayout();
  10. markNeedsCompositingBitsUpdate();
  11. markNeedsPaint();
  12. markNeedsSemanticsUpdate();
  13. visitChildren((RenderObject child) {
  14. child.reassemble();
  15. });
  16. }
  17. /// 将 RenderObject 添加到 RenderObject tree 上
  18. @override
  19. void attach(PipelineOwner owner) {
  20. assert(!_debugDisposed);
  21. super.attach(owner);
  22. if (_needsLayout && _relayoutBoundary != null) {
  23. // Don't enter this block if we've never laid out at all;
  24. // scheduleInitialLayout() will handle it
  25. _needsLayout = false;
  26. markNeedsLayout();
  27. }
  28. if (_needsCompositingBitsUpdate) {
  29. _needsCompositingBitsUpdate = false;
  30. markNeedsCompositingBitsUpdate();
  31. }
  32. if (_needsPaint && _layerHandle.layer != null) {
  33. // Don't enter this block if we've never painted at all;
  34. // scheduleInitialPaint() will handle it
  35. _needsPaint = false;
  36. markNeedsPaint();
  37. }
  38. if (_needsSemanticsUpdate && _semanticsConfiguration.isSemanticBoundary) {
  39. // Don't enter this block if we've never updated semantics at all;
  40. // scheduleInitialSemantics() will handle it
  41. _needsSemanticsUpdate = false;
  42. markNeedsSemanticsUpdate();
  43. }
  44. }
  45. /// 获取 约束
  46. @protected
  47. Constraints get constraints {
  48. if (_constraints == null)
  49. throw StateError('A RenderObject does not have any constraints before it has been laid out.');
  50. return _constraints!;
  51. }
  52. /// 标记脏点,布局
  53. void markNeedsLayout() {
  54. assert(_debugCanPerformMutations);
  55. if (_needsLayout) {
  56. assert(_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout());
  57. return;
  58. }
  59. if (_relayoutBoundary == null) {
  60. _needsLayout = true;
  61. if (parent != null) {
  62. markParentNeedsLayout();
  63. }
  64. return;
  65. }
  66. if (_relayoutBoundary != this) {
  67. markParentNeedsLayout();
  68. } else {
  69. _needsLayout = true;
  70. if (owner != null) {
  71. assert(() {
  72. if (debugPrintMarkNeedsLayoutStacks)
  73. debugPrintStack(label: 'markNeedsLayout() called for $this');
  74. return true;
  75. }());
  76. owner!._nodesNeedingLayout.add(this);
  77. owner!.requestVisualUpdate();
  78. }
  79. }
  80. }
  81. // 合成
  82. void markNeedsCompositingBitsUpdate() {
  83. assert(!_debugDisposed);
  84. if (_needsCompositingBitsUpdate)
  85. return;
  86. _needsCompositingBitsUpdate = true;
  87. if (parent is RenderObject) {
  88. final RenderObject parent = this.parent! as RenderObject;
  89. if (parent._needsCompositingBitsUpdate)
  90. return;
  91. if (!isRepaintBoundary && !parent.isRepaintBoundary) {
  92. parent.markNeedsCompositingBitsUpdate();
  93. return;
  94. }
  95. }
  96. assert(() {
  97. final AbstractNode? parent = this.parent;
  98. if (parent is RenderObject)
  99. return parent._needsCompositing;
  100. return true;
  101. }());
  102. // parent is fine (or there isn't one), but we are dirty
  103. if (owner != null)
  104. owner!._nodesNeedingCompositingBitsUpdate.add(this);
  105. }
  106. /// 绘制
  107. void markNeedsPaint() {
  108. assert(!_debugDisposed);
  109. assert(owner == null || !owner!.debugDoingPaint);
  110. if (_needsPaint)
  111. return;
  112. _needsPaint = true;
  113. if (isRepaintBoundary) {
  114. assert(() {
  115. if (debugPrintMarkNeedsPaintStacks)
  116. debugPrintStack(label: 'markNeedsPaint() called for $this');
  117. return true;
  118. }());
  119. // If we always have our own layer, then we can just repaint
  120. // ourselves without involving any other nodes.
  121. assert(_layerHandle.layer is OffsetLayer);
  122. if (owner != null) {
  123. owner!._nodesNeedingPaint.add(this);
  124. owner!.requestVisualUpdate();
  125. }
  126. } else if (parent is RenderObject) {
  127. final RenderObject parent = this.parent! as RenderObject;
  128. parent.markNeedsPaint();
  129. assert(parent == this.parent);
  130. } else {
  131. assert(() {
  132. if (debugPrintMarkNeedsPaintStacks)
  133. debugPrintStack(label: 'markNeedsPaint() called for $this (root of render tree)');
  134. return true;
  135. }());
  136. if (owner != null)
  137. owner!.requestVisualUpdate();
  138. }
  139. }
  140. }

根据 RenderObject 的 markNeedsLayout 、markNeedsCompositingBitsUpdate 、markNeedsPaint 得出 isRepaintBoundary 就是判断是否继续寻找父级,为 false,则向上寻找父级,直到 isRepaintBoundary = true 为止 。

RenderObjectWidget 源码分析

  1. abstract class RenderObjectWidget extends Widget {
  2. const RenderObjectWidget({ super.key });
  3. @override
  4. @factory
  5. RenderObjectElement createElement();
  6. @protected
  7. @factory
  8. RenderObject createRenderObject(BuildContext context);
  9. @protected
  10. void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
  11. @protected
  12. void didUnmountRenderObject(covariant RenderObject renderObject) { }
  13. }

RenderObjectWidget 是 RenderObjectElement 的配置信息,操作 RenderObject 在 RenderObject tree 上的更新以及 取消挂载 。

RenderObjectElement 源码分析

  1. abstract class RenderObjectElement extends Element {
  2. /// Creates an element that uses the given widget as its configuration.
  3. RenderObjectElement(RenderObjectWidget super.widget);
  4. /// The underlying [RenderObject] for this element.
  5. ///
  6. /// If this element has been [unmount]ed, this getter will throw.
  7. @override
  8. RenderObject get renderObject {
  9. assert(_renderObject != null, '$runtimeType unmounted');
  10. return _renderObject!;
  11. }
  12. RenderObject? _renderObject;
  13. bool _debugDoingBuild = false;
  14. @override
  15. bool get debugDoingBuild => _debugDoingBuild;
  16. RenderObjectElement? _ancestorRenderObjectElement;
  17. RenderObjectElement? _findAncestorRenderObjectElement() {
  18. Element? ancestor = _parent;
  19. while (ancestor != null && ancestor is! RenderObjectElement)
  20. ancestor = ancestor._parent;
  21. return ancestor as RenderObjectElement?;
  22. }
  23. ParentDataElement<ParentData>? _findAncestorParentDataElement() {
  24. Element? ancestor = _parent;
  25. ParentDataElement<ParentData>? result;
  26. while (ancestor != null && ancestor is! RenderObjectElement) {
  27. if (ancestor is ParentDataElement<ParentData>) {
  28. result = ancestor;
  29. break;
  30. }
  31. ancestor = ancestor._parent;
  32. }
  33. assert(() {
  34. if (result == null || ancestor == null) {
  35. return true;
  36. }
  37. // Check that no other ParentDataWidgets want to provide parent data.
  38. final List<ParentDataElement<ParentData>> badAncestors = <ParentDataElement<ParentData>>[];
  39. ancestor = ancestor!._parent;
  40. while (ancestor != null && ancestor is! RenderObjectElement) {
  41. if (ancestor is ParentDataElement<ParentData>) {
  42. badAncestors.add(ancestor! as ParentDataElement<ParentData>);
  43. }
  44. ancestor = ancestor!._parent;
  45. }
  46. if (badAncestors.isNotEmpty) {
  47. badAncestors.insert(0, result);
  48. try {
  49. // We explicitly throw here (even though we immediately redirect the
  50. // exception elsewhere) so that debuggers will notice it when they
  51. // have "break on exception" enabled.
  52. throw FlutterError.fromParts(<DiagnosticsNode>[
  53. ErrorSummary('Incorrect use of ParentDataWidget.'),
  54. ErrorDescription('The following ParentDataWidgets are providing parent data to the same RenderObject:'),
  55. for (final ParentDataElement<ParentData> ancestor in badAncestors)
  56. ErrorDescription('- ${ancestor.widget} (typically placed directly inside a ${(ancestor.widget as ParentDataWidget<ParentData>).debugTypicalAncestorWidgetClass} widget)'),
  57. ErrorDescription('However, a RenderObject can only receive parent data from at most one ParentDataWidget.'),
  58. ErrorHint('Usually, this indicates that at least one of the offending ParentDataWidgets listed above is not placed directly inside a compatible ancestor widget.'),
  59. ErrorDescription('The ownership chain for the RenderObject that received the parent data was:\n ${debugGetCreatorChain(10)}'),
  60. ]);
  61. } on FlutterError catch (e) {
  62. _debugReportException(ErrorSummary('while looking for parent data.'), e, e.stackTrace);
  63. }
  64. }
  65. return true;
  66. }());
  67. return result;
  68. }
  69. @override
  70. void mount(Element? parent, Object? newSlot) {
  71. super.mount(parent, newSlot);
  72. assert(() {
  73. _debugDoingBuild = true;
  74. return true;
  75. }());
  76. _renderObject = (widget as RenderObjectWidget).createRenderObject(this);
  77. assert(!_renderObject!.debugDisposed!);
  78. assert(() {
  79. _debugDoingBuild = false;
  80. return true;
  81. }());
  82. assert(() {
  83. _debugUpdateRenderObjectOwner();
  84. return true;
  85. }());
  86. assert(_slot == newSlot);
  87. attachRenderObject(newSlot);
  88. _dirty = false;
  89. }
  90. @override
  91. void update(covariant RenderObjectWidget newWidget) {
  92. super.update(newWidget);
  93. assert(widget == newWidget);
  94. assert(() {
  95. _debugUpdateRenderObjectOwner();
  96. return true;
  97. }());
  98. _performRebuild(); // calls widget.updateRenderObject()
  99. }
  100. void _debugUpdateRenderObjectOwner() {
  101. assert(() {
  102. renderObject.debugCreator = DebugCreator(this);
  103. return true;
  104. }());
  105. }
  106. @override
  107. void performRebuild() {
  108. _performRebuild(); // calls widget.updateRenderObject()
  109. }
  110. @pragma('vm:prefer-inline')
  111. void _performRebuild() {
  112. assert(() {
  113. _debugDoingBuild = true;
  114. return true;
  115. }());
  116. (widget as RenderObjectWidget).updateRenderObject(this, renderObject);
  117. assert(() {
  118. _debugDoingBuild = false;
  119. return true;
  120. }());
  121. _dirty = false;
  122. }
  123. @protected
  124. List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element>? forgottenChildren, List<Object?>? slots }) {
  125. assert(oldChildren != null);
  126. assert(newWidgets != null);
  127. assert(slots == null || newWidgets.length == slots.length);
  128. Element? replaceWithNullIfForgotten(Element child) {
  129. return forgottenChildren != null && forgottenChildren.contains(child) ? null : child;
  130. }
  131. Object? slotFor(int newChildIndex, Element? previousChild) {
  132. return slots != null
  133. ? slots[newChildIndex]
  134. : IndexedSlot<Element?>(newChildIndex, previousChild);
  135. }
  136. int newChildrenTop = 0;
  137. int oldChildrenTop = 0;
  138. int newChildrenBottom = newWidgets.length - 1;
  139. int oldChildrenBottom = oldChildren.length - 1;
  140. final List<Element> newChildren = oldChildren.length == newWidgets.length ?
  141. oldChildren : List<Element>.filled(newWidgets.length, _NullElement.instance);
  142. Element? previousChild;
  143. // Update the top of the list.
  144. while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
  145. final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
  146. final Widget newWidget = newWidgets[newChildrenTop];
  147. assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
  148. if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
  149. break;
  150. final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
  151. assert(newChild._lifecycleState == _ElementLifecycle.active);
  152. newChildren[newChildrenTop] = newChild;
  153. previousChild = newChild;
  154. newChildrenTop += 1;
  155. oldChildrenTop += 1;
  156. }
  157. // Scan the bottom of the list.
  158. while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
  159. final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);
  160. final Widget newWidget = newWidgets[newChildrenBottom];
  161. assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
  162. if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
  163. break;
  164. oldChildrenBottom -= 1;
  165. newChildrenBottom -= 1;
  166. }
  167. // Scan the old children in the middle of the list.
  168. final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
  169. Map<Key, Element>? oldKeyedChildren;
  170. if (haveOldChildren) {
  171. oldKeyedChildren = <Key, Element>{};
  172. while (oldChildrenTop <= oldChildrenBottom) {
  173. final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
  174. assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
  175. if (oldChild != null) {
  176. if (oldChild.widget.key != null)
  177. oldKeyedChildren[oldChild.widget.key!] = oldChild;
  178. else
  179. deactivateChild(oldChild);
  180. }
  181. oldChildrenTop += 1;
  182. }
  183. }
  184. // Update the middle of the list.
  185. while (newChildrenTop <= newChildrenBottom) {
  186. Element? oldChild;
  187. final Widget newWidget = newWidgets[newChildrenTop];
  188. if (haveOldChildren) {
  189. final Key? key = newWidget.key;
  190. if (key != null) {
  191. oldChild = oldKeyedChildren![key];
  192. if (oldChild != null) {
  193. if (Widget.canUpdate(oldChild.widget, newWidget)) {
  194. // we found a match!
  195. // remove it from oldKeyedChildren so we don't unsync it later
  196. oldKeyedChildren.remove(key);
  197. } else {
  198. // Not a match, let's pretend we didn't see it for now.
  199. oldChild = null;
  200. }
  201. }
  202. }
  203. }
  204. assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));
  205. final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
  206. assert(newChild._lifecycleState == _ElementLifecycle.active);
  207. assert(oldChild == newChild || oldChild == null || oldChild._lifecycleState != _ElementLifecycle.active);
  208. newChildren[newChildrenTop] = newChild;
  209. previousChild = newChild;
  210. newChildrenTop += 1;
  211. }
  212. // We've scanned the whole list.
  213. assert(oldChildrenTop == oldChildrenBottom + 1);
  214. assert(newChildrenTop == newChildrenBottom + 1);
  215. assert(newWidgets.length - newChildrenTop == oldChildren.length - oldChildrenTop);
  216. newChildrenBottom = newWidgets.length - 1;
  217. oldChildrenBottom = oldChildren.length - 1;
  218. // Update the bottom of the list.
  219. while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
  220. final Element oldChild = oldChildren[oldChildrenTop];
  221. assert(replaceWithNullIfForgotten(oldChild) != null);
  222. assert(oldChild._lifecycleState == _ElementLifecycle.active);
  223. final Widget newWidget = newWidgets[newChildrenTop];
  224. assert(Widget.canUpdate(oldChild.widget, newWidget));
  225. final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
  226. assert(newChild._lifecycleState == _ElementLifecycle.active);
  227. assert(oldChild == newChild || oldChild == null || oldChild._lifecycleState != _ElementLifecycle.active);
  228. newChildren[newChildrenTop] = newChild;
  229. previousChild = newChild;
  230. newChildrenTop += 1;
  231. oldChildrenTop += 1;
  232. }
  233. // Clean up any of the remaining middle nodes from the old list.
  234. if (haveOldChildren && oldKeyedChildren!.isNotEmpty) {
  235. for (final Element oldChild in oldKeyedChildren.values) {
  236. if (forgottenChildren == null || !forgottenChildren.contains(oldChild))
  237. deactivateChild(oldChild);
  238. }
  239. }
  240. assert(newChildren.every((Element element) => element is! _NullElement));
  241. return newChildren;
  242. }
  243. @override
  244. void deactivate() {
  245. super.deactivate();
  246. assert(
  247. !renderObject.attached,
  248. 'A RenderObject was still attached when attempting to deactivate its '
  249. 'RenderObjectElement: $renderObject',
  250. );
  251. }
  252. @override
  253. void unmount() {
  254. assert(
  255. !renderObject.debugDisposed!,
  256. 'A RenderObject was disposed prior to its owning element being unmounted: '
  257. '$renderObject',
  258. );
  259. final RenderObjectWidget oldWidget = widget as RenderObjectWidget;
  260. super.unmount();
  261. assert(
  262. !renderObject.attached,
  263. 'A RenderObject was still attached when attempting to unmount its '
  264. 'RenderObjectElement: $renderObject',
  265. );
  266. oldWidget.didUnmountRenderObject(renderObject);
  267. _renderObject!.dispose();
  268. _renderObject = null;
  269. }
  270. void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) {
  271. bool applyParentData = true;
  272. assert(() {
  273. try {
  274. if (!parentDataWidget.debugIsValidRenderObject(renderObject)) {
  275. applyParentData = false;
  276. throw FlutterError.fromParts(<DiagnosticsNode>[
  277. ErrorSummary('Incorrect use of ParentDataWidget.'),
  278. ...parentDataWidget._debugDescribeIncorrectParentDataType(
  279. parentData: renderObject.parentData,
  280. parentDataCreator: _ancestorRenderObjectElement!.widget as RenderObjectWidget,
  281. ownershipChain: ErrorDescription(debugGetCreatorChain(10)),
  282. ),
  283. ]);
  284. }
  285. } on FlutterError catch (e) {
  286. _debugReportException(ErrorSummary('while applying parent data.'), e, e.stackTrace);
  287. }
  288. return true;
  289. }());
  290. if (applyParentData)
  291. parentDataWidget.applyParentData(renderObject);
  292. }
  293. @override
  294. void _updateSlot(Object? newSlot) {
  295. final Object? oldSlot = slot;
  296. assert(oldSlot != newSlot);
  297. super._updateSlot(newSlot);
  298. assert(slot == newSlot);
  299. _ancestorRenderObjectElement!.moveRenderObjectChild(renderObject, oldSlot, slot);
  300. }
  301. @override
  302. void attachRenderObject(Object? newSlot) {
  303. assert(_ancestorRenderObjectElement == null);
  304. _slot = newSlot;
  305. _ancestorRenderObjectElement = _findAncestorRenderObjectElement();
  306. _ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
  307. final ParentDataElement<ParentData>? parentDataElement = _findAncestorParentDataElement();
  308. if (parentDataElement != null)
  309. _updateParentData(parentDataElement.widget as ParentDataWidget<ParentData>);
  310. }
  311. @override
  312. void detachRenderObject() {
  313. if (_ancestorRenderObjectElement != null) {
  314. _ancestorRenderObjectElement!.removeRenderObjectChild(renderObject, slot);
  315. _ancestorRenderObjectElement = null;
  316. }
  317. _slot = null;
  318. }
  319. @protected
  320. void insertRenderObjectChild(covariant RenderObject child, covariant Object? slot) {
  321. assert(() {
  322. throw FlutterError.fromParts(<DiagnosticsNode>[
  323. ErrorSummary('RenderObjectElement.insertChildRenderObject() is deprecated.'),
  324. toDiagnosticsNode(
  325. name: 'insertChildRenderObject() was called on this Element',
  326. style: DiagnosticsTreeStyle.shallow,
  327. ),
  328. ErrorDescription(
  329. 'insertChildRenderObject() has been deprecated in favor of '
  330. 'insertRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 '
  331. 'for details.',
  332. ),
  333. ErrorHint(
  334. 'Rather than overriding insertChildRenderObject() in your '
  335. 'RenderObjectElement subclass, override insertRenderObjectChild() instead, '
  336. "and DON'T call super.insertRenderObjectChild(). If you're implementing a "
  337. 'new RenderObjectElement, you should override/implement '
  338. 'insertRenderObjectChild(), moveRenderObjectChild(), and '
  339. 'removeRenderObjectChild().',
  340. ),
  341. ]);
  342. }());
  343. }
  344. @protected
  345. void moveRenderObjectChild(covariant RenderObject child, covariant Object? oldSlot, covariant Object? newSlot) {
  346. assert(() {
  347. throw FlutterError.fromParts(<DiagnosticsNode>[
  348. ErrorSummary('RenderObjectElement.moveChildRenderObject() is deprecated.'),
  349. toDiagnosticsNode(
  350. name: 'super.moveChildRenderObject() was called on this Element',
  351. style: DiagnosticsTreeStyle.shallow,
  352. ),
  353. ErrorDescription(
  354. 'moveChildRenderObject() has been deprecated in favor of '
  355. 'moveRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 '
  356. 'for details.',
  357. ),
  358. ErrorHint(
  359. 'Rather than overriding moveChildRenderObject() in your '
  360. 'RenderObjectElement subclass, override moveRenderObjectChild() instead, '
  361. "and DON'T call super.moveRenderObjectChild(). If you're implementing a "
  362. 'new RenderObjectElement, you should override/implement '
  363. 'insertRenderObjectChild(), moveRenderObjectChild(), and '
  364. 'removeRenderObjectChild().',
  365. ),
  366. ]);
  367. }());
  368. }
  369. /// Remove the given child from [renderObject].
  370. ///
  371. /// The given child is guaranteed to have been inserted at the given `slot`
  372. /// and have [renderObject] as its parent.
  373. @protected
  374. void removeRenderObjectChild(covariant RenderObject child, covariant Object? slot) {
  375. assert(() {
  376. throw FlutterError.fromParts(<DiagnosticsNode>[
  377. ErrorSummary('RenderObjectElement.removeChildRenderObject() is deprecated.'),
  378. toDiagnosticsNode(
  379. name: 'super.removeChildRenderObject() was called on this Element',
  380. style: DiagnosticsTreeStyle.shallow,
  381. ),
  382. ErrorDescription(
  383. 'removeChildRenderObject() has been deprecated in favor of '
  384. 'removeRenderObjectChild(). See https://github.com/flutter/flutter/issues/63269 '
  385. 'for details.',
  386. ),
  387. ErrorHint(
  388. 'Rather than overriding removeChildRenderObject() in your '
  389. 'RenderObjectElement subclass, override removeRenderObjectChild() instead, '
  390. "and DON'T call super.removeRenderObjectChild(). If you're implementing a "
  391. 'new RenderObjectElement, you should override/implement '
  392. 'insertRenderObjectChild(), moveRenderObjectChild(), and '
  393. 'removeRenderObjectChild().',
  394. ),
  395. ]);
  396. }());
  397. }
  398. @override
  399. void debugFillProperties(DiagnosticPropertiesBuilder properties) {
  400. super.debugFillProperties(properties);
  401. properties.add(DiagnosticsProperty<RenderObject>('renderObject', _renderObject, defaultValue: null));
  402. }
  403. }

RenderObjectElement 维护 Element 的新旧 slot 的值,以及位置,其方法会触发 RenderObject 在 RenderObject tree上的 slot 改变。

三者之间的流程图

Widget 和 Element 、RenderObject之间的关系 - 图2