1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// @docImport 'dart:ui';
6///
7/// @docImport 'package:flutter/animation.dart';
8/// @docImport 'package:flutter/material.dart';
9/// @docImport 'package:flutter/widgets.dart';
10/// @docImport 'package:flutter_test/flutter_test.dart';
11library;
12
13import 'dart:async';
14import 'dart:collection';
15
16import 'package:flutter/foundation.dart';
17import 'package:flutter/rendering.dart';
18
19import 'binding.dart';
20import 'debug.dart';
21import 'focus_manager.dart';
22import 'inherited_model.dart';
23import 'notification_listener.dart';
24import 'widget_inspector.dart';
25
26export 'package:flutter/foundation.dart'
27 show
28 factory,
29 immutable,
30 mustCallSuper,
31 optionalTypeArgs,
32 protected,
33 required,
34 visibleForTesting;
35export 'package:flutter/foundation.dart'
36 show ErrorDescription, ErrorHint, ErrorSummary, FlutterError, debugPrint, debugPrintStack;
37export 'package:flutter/foundation.dart' show DiagnosticLevel, DiagnosticsNode;
38export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;
39export 'package:flutter/foundation.dart' show ValueChanged, ValueGetter, ValueSetter, VoidCallback;
40export 'package:flutter/rendering.dart'
41 show RenderBox, RenderObject, debugDumpLayerTree, debugDumpRenderTree;
42
43// Examples can assume:
44// late BuildContext context;
45// void setState(VoidCallback fn) { }
46// abstract class RenderFrogJar extends RenderObject { }
47// abstract class FrogJar extends RenderObjectWidget { const FrogJar({super.key}); }
48// abstract class FrogJarParentData extends ParentData { late Size size; }
49// abstract class SomeWidget extends StatefulWidget { const SomeWidget({super.key}); }
50// typedef ChildWidget = Placeholder;
51// class _SomeWidgetState extends State { @override Widget build(BuildContext context) => widget; }
52// abstract class RenderFoo extends RenderObject { }
53// abstract class Foo extends RenderObjectWidget { const Foo({super.key}); }
54// abstract class StatefulWidgetX { const StatefulWidgetX({this.key}); final Key? key; Widget build(BuildContext context, State state); }
55// class SpecialWidget extends StatelessWidget { const SpecialWidget({ super.key, this.handler }); final VoidCallback? handler; @override Widget build(BuildContext context) => this; }
56// late Object? _myState, newValue;
57// int _counter = 0;
58// Future getApplicationDocumentsDirectory() async => Directory('');
59// late AnimationController animation;
60
61class _DebugOnly {
62 const _DebugOnly();
63}
64
65/// An annotation used by test_analysis package to verify patterns are followed
66/// that allow for tree-shaking of both fields and their initializers. This
67/// annotation has no impact on code by itself, but indicates the following pattern
68/// should be followed for a given field:
69///
70/// ```dart
71/// class Bar {
72/// final Object? bar = kDebugMode ? Object() : null;
73/// }
74/// ```
75const _DebugOnly _debugOnly = _DebugOnly();
76
77// KEYS
78
79/// A key that takes its identity from the object used as its value.
80///
81/// Used to tie the identity of a widget to the identity of an object used to
82/// generate that widget.
83///
84/// See also:
85///
86/// * [Key], the base class for all keys.
87/// * The discussion at [Widget.key] for more information about how widgets use
88/// keys.
89class ObjectKey extends LocalKey {
90 /// Creates a key that uses [identical] on [value] for its [operator==].
91 const ObjectKey(this.value);
92
93 /// The object whose identity is used by this key's [operator==].
94 final Object? value;
95
96 @override
97 bool operator ==(Object other) {
98 if (other.runtimeType != runtimeType) {
99 return false;
100 }
101 return other is ObjectKey && identical(other.value, value);
102 }
103
104 @override
105 int get hashCode => Object.hash(runtimeType, identityHashCode(value));
106
107 @override
108 String toString() {
109 if (runtimeType == ObjectKey) {
110 return '[${describeIdentity(value)}]';
111 }
112 return '[${objectRuntimeType(this, 'ObjectKey')} ${describeIdentity(value)}]';
113 }
114}
115
116/// A key that is unique across the entire app.
117///
118/// Global keys uniquely identify elements. Global keys provide access to other
119/// objects that are associated with those elements, such as [BuildContext].
120/// For [StatefulWidget]s, global keys also provide access to [State].
121///
122/// Widgets that have global keys reparent their subtrees when they are moved
123/// from one location in the tree to another location in the tree. In order to
124/// reparent its subtree, a widget must arrive at its new location in the tree
125/// in the same animation frame in which it was removed from its old location in
126/// the tree.
127///
128/// Reparenting an [Element] using a global key is relatively expensive, as
129/// this operation will trigger a call to [State.deactivate] on the associated
130/// [State] and all of its descendants; then force all widgets that depends
131/// on an [InheritedWidget] to rebuild.
132///
133/// If you don't need any of the features listed above, consider using a [Key],
134/// [ValueKey], [ObjectKey], or [UniqueKey] instead.
135///
136/// You cannot simultaneously include two widgets in the tree with the same
137/// global key. Attempting to do so will assert at runtime.
138///
139/// ## Pitfalls
140///
141/// GlobalKeys should not be re-created on every build. They should usually be
142/// long-lived objects owned by a [State] object, for example.
143///
144/// Creating a new GlobalKey on every build will throw away the state of the
145/// subtree associated with the old key and create a new fresh subtree for the
146/// new key. Besides harming performance, this can also cause unexpected
147/// behavior in widgets in the subtree. For example, a [GestureDetector] in the
148/// subtree will be unable to track ongoing gestures since it will be recreated
149/// on each build.
150///
151/// Instead, a good practice is to let a State object own the GlobalKey, and
152/// instantiate it outside the build method, such as in [State.initState].
153///
154/// See also:
155///
156/// * The discussion at [Widget.key] for more information about how widgets use
157/// keys.
158@optionalTypeArgs
159abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
160 /// Creates a [LabeledGlobalKey], which is a [GlobalKey] with a label used for
161 /// debugging.
162 ///
163 /// The label is purely for debugging and not used for comparing the identity
164 /// of the key.
165 factory GlobalKey({String? debugLabel}) => LabeledGlobalKey<T>(debugLabel);
166
167 /// Creates a global key without a label.
168 ///
169 /// Used by subclasses because the factory constructor shadows the implicit
170 /// constructor.
171 const GlobalKey.constructor() : super.empty();
172
173 Element? get _currentElement => WidgetsBinding.instance.buildOwner!._globalKeyRegistry[this];
174
175 /// The build context in which the widget with this key builds.
176 ///
177 /// The current context is null if there is no widget in the tree that matches
178 /// this global key.
179 BuildContext? get currentContext => _currentElement;
180
181 /// The widget in the tree that currently has this global key.
182 ///
183 /// The current widget is null if there is no widget in the tree that matches
184 /// this global key.
185 Widget? get currentWidget => _currentElement?.widget;
186
187 /// The [State] for the widget in the tree that currently has this global key.
188 ///
189 /// The current state is null if (1) there is no widget in the tree that
190 /// matches this global key, (2) that widget is not a [StatefulWidget], or the
191 /// associated [State] object is not a subtype of `T`.
192 T? get currentState => switch (_currentElement) {
193 StatefulElement(:final T state) => state,
194 _ => null,
195 };
196}
197
198/// A global key with a debugging label.
199///
200/// The debug label is useful for documentation and for debugging. The label
201/// does not affect the key's identity.
202@optionalTypeArgs
203class LabeledGlobalKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
204 /// Creates a global key with a debugging label.
205 ///
206 /// The label does not affect the key's identity.
207 // ignore: prefer_const_constructors_in_immutables , never use const for this class
208 LabeledGlobalKey(this._debugLabel) : super.constructor();
209
210 final String? _debugLabel;
211
212 @override
213 String toString() {
214 final String label = _debugLabel != null ? ' $_debugLabel' : '';
215 if (runtimeType == LabeledGlobalKey) {
216 return '[GlobalKey#${shortHash(this)}$label]';
217 }
218 return '[${describeIdentity(this)}$label]';
219 }
220}
221
222/// A global key that takes its identity from the object used as its value.
223///
224/// Used to tie the identity of a widget to the identity of an object used to
225/// generate that widget.
226///
227/// Any [GlobalObjectKey] created for the same object will match.
228///
229/// If the object is not private, then it is possible that collisions will occur
230/// where independent widgets will reuse the same object as their
231/// [GlobalObjectKey] value in a different part of the tree, leading to a global
232/// key conflict. To avoid this problem, create a private [GlobalObjectKey]
233/// subclass, as in:
234///
235/// ```dart
236/// class _MyKey extends GlobalObjectKey {
237/// const _MyKey(super.value);
238/// }
239/// ```
240///
241/// Since the [runtimeType] of the key is part of its identity, this will
242/// prevent clashes with other [GlobalObjectKey]s even if they have the same
243/// value.
244@optionalTypeArgs
245class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
246 /// Creates a global key that uses [identical] on [value] for its [operator==].
247 const GlobalObjectKey(this.value) : super.constructor();
248
249 /// The object whose identity is used by this key's [operator==].
250 final Object value;
251
252 @override
253 bool operator ==(Object other) {
254 if (other.runtimeType != runtimeType) {
255 return false;
256 }
257 return other is GlobalObjectKey<T> && identical(other.value, value);
258 }
259
260 @override
261 int get hashCode => identityHashCode(value);
262
263 @override
264 String toString() {
265 String selfType = objectRuntimeType(this, 'GlobalObjectKey');
266 // The runtimeType string of a GlobalObjectKey() returns 'GlobalObjectKey>'
267 // because GlobalObjectKey is instantiated to its bounds. To avoid cluttering the output
268 // we remove the suffix.
269 const String suffix = '<State<StatefulWidget>>';
270 if (selfType.endsWith(suffix)) {
271 selfType = selfType.substring(0, selfType.length - suffix.length);
272 }
273 return '[$selfType ${describeIdentity(value)}]';
274 }
275}
276
277/// Describes the configuration for an [Element].
278///
279/// Widgets are the central class hierarchy in the Flutter framework. A widget
280/// is an immutable description of part of a user interface. Widgets can be
281/// inflated into elements, which manage the underlying render tree.
282///
283/// Widgets themselves have no mutable state (all their fields must be final).
284/// If you wish to associate mutable state with a widget, consider using a
285/// [StatefulWidget], which creates a [State] object (via
286/// [StatefulWidget.createState]) whenever it is inflated into an element and
287/// incorporated into the tree.
288///
289/// A given widget can be included in the tree zero or more times. In particular
290/// a given widget can be placed in the tree multiple times. Each time a widget
291/// is placed in the tree, it is inflated into an [Element], which means a
292/// widget that is incorporated into the tree multiple times will be inflated
293/// multiple times.
294///
295/// The [key] property controls how one widget replaces another widget in the
296/// tree. If the [runtimeType] and [key] properties of the two widgets are
297/// [operator==], respectively, then the new widget replaces the old widget by
298/// updating the underlying element (i.e., by calling [Element.update] with the
299/// new widget). Otherwise, the old element is removed from the tree, the new
300/// widget is inflated into an element, and the new element is inserted into the
301/// tree.
302///
303/// See also:
304///
305/// * [StatefulWidget] and [State], for widgets that can build differently
306/// several times over their lifetime.
307/// * [InheritedWidget], for widgets that introduce ambient state that can
308/// be read by descendant widgets.
309/// * [StatelessWidget], for widgets that always build the same way given a
310/// particular configuration and ambient state.
311@immutable
312abstract class Widget extends DiagnosticableTree {
313 /// Initializes [key] for subclasses.
314 const Widget({this.key});
315
316 /// Controls how one widget replaces another widget in the tree.
317 ///
318 /// If the [runtimeType] and [key] properties of the two widgets are
319 /// [operator==], respectively, then the new widget replaces the old widget by
320 /// updating the underlying element (i.e., by calling [Element.update] with the
321 /// new widget). Otherwise, the old element is removed from the tree, the new
322 /// widget is inflated into an element, and the new element is inserted into the
323 /// tree.
324 ///
325 /// In addition, using a [GlobalKey] as the widget's [key] allows the element
326 /// to be moved around the tree (changing parent) without losing state. When a
327 /// new widget is found (its key and type do not match a previous widget in
328 /// the same location), but there was a widget with that same global key
329 /// elsewhere in the tree in the previous frame, then that widget's element is
330 /// moved to the new location.
331 ///
332 /// Generally, a widget that is the only child of another widget does not need
333 /// an explicit key.
334 ///
335 /// See also:
336 ///
337 /// * The discussions at [Key] and [GlobalKey].
338 final Key? key;
339
340 /// Inflates this configuration to a concrete instance.
341 ///
342 /// A given widget can be included in the tree zero or more times. In particular
343 /// a given widget can be placed in the tree multiple times. Each time a widget
344 /// is placed in the tree, it is inflated into an [Element], which means a
345 /// widget that is incorporated into the tree multiple times will be inflated
346 /// multiple times.
347 @protected
348 @factory
349 Element createElement();
350
351 /// A short, textual description of this widget.
352 @override
353 String toStringShort() {
354 final String type = objectRuntimeType(this, 'Widget');
355 return key == null ? type : '$type-$key';
356 }
357
358 @override
359 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
360 super.debugFillProperties(properties);
361 properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
362 }
363
364 @override
365 @nonVirtual
366 bool operator ==(Object other) => super == other;
367
368 @override
369 @nonVirtual
370 int get hashCode => super.hashCode;
371
372 /// Whether the `newWidget` can be used to update an [Element] that currently
373 /// has the `oldWidget` as its configuration.
374 ///
375 /// An element that uses a given widget as its configuration can be updated to
376 /// use another widget as its configuration if, and only if, the two widgets
377 /// have [runtimeType] and [key] properties that are [operator==].
378 ///
379 /// If the widgets have no key (their key is null), then they are considered a
380 /// match if they have the same type, even if their children are completely
381 /// different.
382 static bool canUpdate(Widget oldWidget, Widget newWidget) {
383 return oldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key;
384 }
385
386 // Return a numeric encoding of the specific `Widget` concrete subtype.
387 // This is used in `Element.updateChild` to determine if a hot reload modified the
388 // superclass of a mounted element's configuration. The encoding of each `Widget`
389 // must match the corresponding `Element` encoding in `Element._debugConcreteSubtype`.
390 static int _debugConcreteSubtype(Widget widget) {
391 return widget is StatefulWidget
392 ? 1
393 : widget is StatelessWidget
394 ? 2
395 : 0;
396 }
397}
398
399/// A widget that does not require mutable state.
400///
401/// A stateless widget is a widget that describes part of the user interface by
402/// building a constellation of other widgets that describe the user interface
403/// more concretely. The building process continues recursively until the
404/// description of the user interface is fully concrete (e.g., consists
405/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
406///
407/// {@youtube 560 315 https://www.youtube.com/watch?v=wE7khGHVkYY}
408///
409/// Stateless widget are useful when the part of the user interface you are
410/// describing does not depend on anything other than the configuration
411/// information in the object itself and the [BuildContext] in which the widget
412/// is inflated. For compositions that can change dynamically, e.g. due to
413/// having an internal clock-driven state, or depending on some system state,
414/// consider using [StatefulWidget].
415///
416/// ## Performance considerations
417///
418/// The [build] method of a stateless widget is typically only called in three
419/// situations: the first time the widget is inserted in the tree, when the
420/// widget's parent changes its configuration (see [Element.rebuild]), and when
421/// an [InheritedWidget] it depends on changes.
422///
423/// If a widget's parent will regularly change the widget's configuration, or if
424/// it depends on inherited widgets that frequently change, then it is important
425/// to optimize the performance of the [build] method to maintain a fluid
426/// rendering performance.
427///
428/// There are several techniques one can use to minimize the impact of
429/// rebuilding a stateless widget:
430///
431/// * Minimize the number of nodes transitively created by the build method and
432/// any widgets it creates. For example, instead of an elaborate arrangement
433/// of [Row]s, [Column]s, [Padding]s, and [SizedBox]es to position a single
434/// child in a particularly fancy manner, consider using just an [Align] or a
435/// [CustomSingleChildLayout]. Instead of an intricate layering of multiple
436/// [Container]s and with [Decoration]s to draw just the right graphical
437/// effect, consider a single [CustomPaint] widget.
438///
439/// * Use `const` widgets where possible, and provide a `const` constructor for
440/// the widget so that users of the widget can also do so.
441///
442/// * Consider refactoring the stateless widget into a stateful widget so that
443/// it can use some of the techniques described at [StatefulWidget], such as
444/// caching common parts of subtrees and using [GlobalKey]s when changing the
445/// tree structure.
446///
447/// * If the widget is likely to get rebuilt frequently due to the use of
448/// [InheritedWidget]s, consider refactoring the stateless widget into
449/// multiple widgets, with the parts of the tree that change being pushed to
450/// the leaves. For example instead of building a tree with four widgets, the
451/// inner-most widget depending on the [Theme], consider factoring out the
452/// part of the build function that builds the inner-most widget into its own
453/// widget, so that only the inner-most widget needs to be rebuilt when the
454/// theme changes.
455/// {@template flutter.flutter.widgets.framework.prefer_const_over_helper}
456/// * When trying to create a reusable piece of UI, prefer using a widget
457/// rather than a helper method. For example, if there was a function used to
458/// build a widget, a [State.setState] call would require Flutter to entirely
459/// rebuild the returned wrapping widget. If a [Widget] was used instead,
460/// Flutter would be able to efficiently re-render only those parts that
461/// really need to be updated. Even better, if the created widget is `const`,
462/// Flutter would short-circuit most of the rebuild work.
463/// {@endtemplate}
464///
465/// This video gives more explanations on why `const` constructors are important
466/// and why a [Widget] is better than a helper method.
467///
468/// {@youtube 560 315 https://www.youtube.com/watch?v=IOyq-eTRhvo}
469///
470/// {@tool snippet}
471///
472/// The following is a skeleton of a stateless widget subclass called `GreenFrog`.
473///
474/// Normally, widgets have more constructor arguments, each of which corresponds
475/// to a `final` property.
476///
477/// ```dart
478/// class GreenFrog extends StatelessWidget {
479/// const GreenFrog({ super.key });
480///
481/// @override
482/// Widget build(BuildContext context) {
483/// return Container(color: const Color(0xFF2DBD3A));
484/// }
485/// }
486/// ```
487/// {@end-tool}
488///
489/// {@tool snippet}
490///
491/// This next example shows the more generic widget `Frog` which can be given
492/// a color and a child:
493///
494/// ```dart
495/// class Frog extends StatelessWidget {
496/// const Frog({
497/// super.key,
498/// this.color = const Color(0xFF2DBD3A),
499/// this.child,
500/// });
501///
502/// final Color color;
503/// final Widget? child;
504///
505/// @override
506/// Widget build(BuildContext context) {
507/// return ColoredBox(color: color, child: child);
508/// }
509/// }
510/// ```
511/// {@end-tool}
512///
513/// By convention, widget constructors only use named arguments. Also by
514/// convention, the first argument is [key], and the last argument is `child`,
515/// `children`, or the equivalent.
516///
517/// See also:
518///
519/// * [StatefulWidget] and [State], for widgets that can build differently
520/// several times over their lifetime.
521/// * [InheritedWidget], for widgets that introduce ambient state that can
522/// be read by descendant widgets.
523abstract class StatelessWidget extends Widget {
524 /// Initializes [key] for subclasses.
525 const StatelessWidget({super.key});
526
527 /// Creates a [StatelessElement] to manage this widget's location in the tree.
528 ///
529 /// It is uncommon for subclasses to override this method.
530 @override
531 StatelessElement createElement() => StatelessElement(this);
532
533 /// Describes the part of the user interface represented by this widget.
534 ///
535 /// The framework calls this method when this widget is inserted into the tree
536 /// in a given [BuildContext] and when the dependencies of this widget change
537 /// (e.g., an [InheritedWidget] referenced by this widget changes). This
538 /// method can potentially be called in every frame and should not have any side
539 /// effects beyond building a widget.
540 ///
541 /// The framework replaces the subtree below this widget with the widget
542 /// returned by this method, either by updating the existing subtree or by
543 /// removing the subtree and inflating a new subtree, depending on whether the
544 /// widget returned by this method can update the root of the existing
545 /// subtree, as determined by calling [Widget.canUpdate].
546 ///
547 /// Typically implementations return a newly created constellation of widgets
548 /// that are configured with information from this widget's constructor and
549 /// from the given [BuildContext].
550 ///
551 /// The given [BuildContext] contains information about the location in the
552 /// tree at which this widget is being built. For example, the context
553 /// provides the set of inherited widgets for this location in the tree. A
554 /// given widget might be built with multiple different [BuildContext]
555 /// arguments over time if the widget is moved around the tree or if the
556 /// widget is inserted into the tree in multiple places at once.
557 ///
558 /// The implementation of this method must only depend on:
559 ///
560 /// * the fields of the widget, which themselves must not change over time,
561 /// and
562 /// * any ambient state obtained from the `context` using
563 /// [BuildContext.dependOnInheritedWidgetOfExactType].
564 ///
565 /// If a widget's [build] method is to depend on anything else, use a
566 /// [StatefulWidget] instead.
567 ///
568 /// See also:
569 ///
570 /// * [StatelessWidget], which contains the discussion on performance considerations.
571 @protected
572 Widget build(BuildContext context);
573}
574
575/// A widget that has mutable state.
576///
577/// State is information that (1) can be read synchronously when the widget is
578/// built and (2) might change during the lifetime of the widget. It is the
579/// responsibility of the widget implementer to ensure that the [State] is
580/// promptly notified when such state changes, using [State.setState].
581///
582/// A stateful widget is a widget that describes part of the user interface by
583/// building a constellation of other widgets that describe the user interface
584/// more concretely. The building process continues recursively until the
585/// description of the user interface is fully concrete (e.g., consists
586/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
587///
588/// Stateful widgets are useful when the part of the user interface you are
589/// describing can change dynamically, e.g. due to having an internal
590/// clock-driven state, or depending on some system state. For compositions that
591/// depend only on the configuration information in the object itself and the
592/// [BuildContext] in which the widget is inflated, consider using
593/// [StatelessWidget].
594///
595/// {@youtube 560 315 https://www.youtube.com/watch?v=AqCMFXEmf3w}
596///
597/// [StatefulWidget] instances themselves are immutable and store their mutable
598/// state either in separate [State] objects that are created by the
599/// [createState] method, or in objects to which that [State] subscribes, for
600/// example [Stream] or [ChangeNotifier] objects, to which references are stored
601/// in final fields on the [StatefulWidget] itself.
602///
603/// The framework calls [createState] whenever it inflates a
604/// [StatefulWidget], which means that multiple [State] objects might be
605/// associated with the same [StatefulWidget] if that widget has been inserted
606/// into the tree in multiple places. Similarly, if a [StatefulWidget] is
607/// removed from the tree and later inserted in to the tree again, the framework
608/// will call [createState] again to create a fresh [State] object, simplifying
609/// the lifecycle of [State] objects.
610///
611/// A [StatefulWidget] keeps the same [State] object when moving from one
612/// location in the tree to another if its creator used a [GlobalKey] for its
613/// [key]. Because a widget with a [GlobalKey] can be used in at most one
614/// location in the tree, a widget that uses a [GlobalKey] has at most one
615/// associated element. The framework takes advantage of this property when
616/// moving a widget with a global key from one location in the tree to another
617/// by grafting the (unique) subtree associated with that widget from the old
618/// location to the new location (instead of recreating the subtree at the new
619/// location). The [State] objects associated with [StatefulWidget] are grafted
620/// along with the rest of the subtree, which means the [State] object is reused
621/// (instead of being recreated) in the new location. However, in order to be
622/// eligible for grafting, the widget must be inserted into the new location in
623/// the same animation frame in which it was removed from the old location.
624///
625/// ## Performance considerations
626///
627/// There are two primary categories of [StatefulWidget]s.
628///
629/// The first is one which allocates resources in [State.initState] and disposes
630/// of them in [State.dispose], but which does not depend on [InheritedWidget]s
631/// or call [State.setState]. Such widgets are commonly used at the root of an
632/// application or page, and communicate with subwidgets via [ChangeNotifier]s,
633/// [Stream]s, or other such objects. Stateful widgets following such a pattern
634/// are relatively cheap (in terms of CPU and GPU cycles), because they are
635/// built once then never update. They can, therefore, have somewhat complicated
636/// and deep build methods.
637///
638/// The second category is widgets that use [State.setState] or depend on
639/// [InheritedWidget]s. These will typically rebuild many times during the
640/// application's lifetime, and it is therefore important to minimize the impact
641/// of rebuilding such a widget. (They may also use [State.initState] or
642/// [State.didChangeDependencies] and allocate resources, but the important part
643/// is that they rebuild.)
644///
645/// There are several techniques one can use to minimize the impact of
646/// rebuilding a stateful widget:
647///
648/// * Push the state to the leaves. For example, if your page has a ticking
649/// clock, rather than putting the state at the top of the page and
650/// rebuilding the entire page each time the clock ticks, create a dedicated
651/// clock widget that only updates itself.
652///
653/// * Minimize the number of nodes transitively created by the build method and
654/// any widgets it creates. Ideally, a stateful widget would only create a
655/// single widget, and that widget would be a [RenderObjectWidget].
656/// (Obviously this isn't always practical, but the closer a widget gets to
657/// this ideal, the more efficient it will be.)
658///
659/// * If a subtree does not change, cache the widget that represents that
660/// subtree and re-use it each time it can be used. To do this, assign
661/// a widget to a `final` state variable and re-use it in the build method. It
662/// is massively more efficient for a widget to be re-used than for a new (but
663/// identically-configured) widget to be created. Another caching strategy
664/// consists in extracting the mutable part of the widget into a [StatefulWidget]
665/// which accepts a child parameter.
666///
667/// * Use `const` widgets where possible. (This is equivalent to caching a
668/// widget and re-using it.)
669///
670/// * Avoid changing the depth of any created subtrees or changing the type of
671/// any widgets in the subtree. For example, rather than returning either the
672/// child or the child wrapped in an [IgnorePointer], always wrap the child
673/// widget in an [IgnorePointer] and control the [IgnorePointer.ignoring]
674/// property. This is because changing the depth of the subtree requires
675/// rebuilding, laying out, and painting the entire subtree, whereas just
676/// changing the property will require the least possible change to the
677/// render tree (in the case of [IgnorePointer], for example, no layout or
678/// repaint is necessary at all).
679///
680/// * If the depth must be changed for some reason, consider wrapping the
681/// common parts of the subtrees in widgets that have a [GlobalKey] that
682/// remains consistent for the life of the stateful widget. (The
683/// [KeyedSubtree] widget may be useful for this purpose if no other widget
684/// can conveniently be assigned the key.)
685///
686/// {@macro flutter.flutter.widgets.framework.prefer_const_over_helper}
687///
688/// This video gives more explanations on why `const` constructors are important
689/// and why a [Widget] is better than a helper method.
690///
691/// {@youtube 560 315 https://www.youtube.com/watch?v=IOyq-eTRhvo}
692///
693/// For more details on the mechanics of rebuilding a widget, see
694/// the discussion at [Element.rebuild].
695///
696/// {@tool snippet}
697///
698/// This is a skeleton of a stateful widget subclass called `YellowBird`.
699///
700/// In this example, the [State] has no actual state. State is normally
701/// represented as private member fields. Also, normally widgets have more
702/// constructor arguments, each of which corresponds to a `final` property.
703///
704/// ```dart
705/// class YellowBird extends StatefulWidget {
706/// const YellowBird({ super.key });
707///
708/// @override
709/// State<YellowBird> createState() => _YellowBirdState();
710/// }
711///
712/// class _YellowBirdState extends State<YellowBird> {
713/// @override
714/// Widget build(BuildContext context) {
715/// return Container(color: const Color(0xFFFFE306));
716/// }
717/// }
718/// ```
719/// {@end-tool}
720/// {@tool snippet}
721///
722/// This example shows the more generic widget `Bird` which can be given a
723/// color and a child, and which has some internal state with a method that
724/// can be called to mutate it:
725///
726/// ```dart
727/// class Bird extends StatefulWidget {
728/// const Bird({
729/// super.key,
730/// this.color = const Color(0xFFFFE306),
731/// this.child,
732/// });
733///
734/// final Color color;
735/// final Widget? child;
736///
737/// @override
738/// State<Bird> createState() => _BirdState();
739/// }
740///
741/// class _BirdState extends State<Bird> {
742/// double _size = 1.0;
743///
744/// void grow() {
745/// setState(() { _size += 0.1; });
746/// }
747///
748/// @override
749/// Widget build(BuildContext context) {
750/// return Container(
751/// color: widget.color,
752/// transform: Matrix4.diagonal3Values(_size, _size, 1.0),
753/// child: widget.child,
754/// );
755/// }
756/// }
757/// ```
758/// {@end-tool}
759///
760/// By convention, widget constructors only use named arguments. Also by
761/// convention, the first argument is [key], and the last argument is `child`,
762/// `children`, or the equivalent.
763///
764/// See also:
765///
766/// * [State], where the logic behind a [StatefulWidget] is hosted.
767/// * [StatelessWidget], for widgets that always build the same way given a
768/// particular configuration and ambient state.
769/// * [InheritedWidget], for widgets that introduce ambient state that can
770/// be read by descendant widgets.
771abstract class StatefulWidget extends Widget {
772 /// Initializes [key] for subclasses.
773 const StatefulWidget({super.key});
774
775 /// Creates a [StatefulElement] to manage this widget's location in the tree.
776 ///
777 /// It is uncommon for subclasses to override this method.
778 @override
779 StatefulElement createElement() => StatefulElement(this);
780
781 /// Creates the mutable state for this widget at a given location in the tree.
782 ///
783 /// Subclasses should override this method to return a newly created
784 /// instance of their associated [State] subclass:
785 ///
786 /// ```dart
787 /// @override
788 /// State<SomeWidget> createState() => _SomeWidgetState();
789 /// ```
790 ///
791 /// The framework can call this method multiple times over the lifetime of
792 /// a [StatefulWidget]. For example, if the widget is inserted into the tree
793 /// in multiple locations, the framework will create a separate [State] object
794 /// for each location. Similarly, if the widget is removed from the tree and
795 /// later inserted into the tree again, the framework will call [createState]
796 /// again to create a fresh [State] object, simplifying the lifecycle of
797 /// [State] objects.
798 @protected
799 @factory
800 State createState();
801}
802
803/// Tracks the lifecycle of [State] objects when asserts are enabled.
804enum _StateLifecycle {
805 /// The [State] object has been created. [State.initState] is called at this
806 /// time.
807 created,
808
809 /// The [State.initState] method has been called but the [State] object is
810 /// not yet ready to build. [State.didChangeDependencies] is called at this time.
811 initialized,
812
813 /// The [State] object is ready to build and [State.dispose] has not yet been
814 /// called.
815 ready,
816
817 /// The [State.dispose] method has been called and the [State] object is
818 /// no longer able to build.
819 defunct,
820}
821
822/// The signature of [State.setState] functions.
823typedef StateSetter = void Function(VoidCallback fn);
824
825/// The logic and internal state for a [StatefulWidget].
826///
827/// State is information that (1) can be read synchronously when the widget is
828/// built and (2) might change during the lifetime of the widget. It is the
829/// responsibility of the widget implementer to ensure that the [State] is
830/// promptly notified when such state changes, using [State.setState].
831///
832/// [State] objects are created by the framework by calling the
833/// [StatefulWidget.createState] method when inflating a [StatefulWidget] to
834/// insert it into the tree. Because a given [StatefulWidget] instance can be
835/// inflated multiple times (e.g., the widget is incorporated into the tree in
836/// multiple places at once), there might be more than one [State] object
837/// associated with a given [StatefulWidget] instance. Similarly, if a
838/// [StatefulWidget] is removed from the tree and later inserted in to the tree
839/// again, the framework will call [StatefulWidget.createState] again to create
840/// a fresh [State] object, simplifying the lifecycle of [State] objects.
841///
842/// [State] objects have the following lifecycle:
843///
844/// * The framework creates a [State] object by calling
845/// [StatefulWidget.createState].
846/// * The newly created [State] object is associated with a [BuildContext].
847/// This association is permanent: the [State] object will never change its
848/// [BuildContext]. However, the [BuildContext] itself can be moved around
849/// the tree along with its subtree. At this point, the [State] object is
850/// considered [mounted].
851/// * The framework calls [initState]. Subclasses of [State] should override
852/// [initState] to perform one-time initialization that depends on the
853/// [BuildContext] or the widget, which are available as the [context] and
854/// [widget] properties, respectively, when the [initState] method is
855/// called.
856/// * The framework calls [didChangeDependencies]. Subclasses of [State] should
857/// override [didChangeDependencies] to perform initialization involving
858/// [InheritedWidget]s. If [BuildContext.dependOnInheritedWidgetOfExactType] is
859/// called, the [didChangeDependencies] method will be called again if the
860/// inherited widgets subsequently change or if the widget moves in the tree.
861/// * At this point, the [State] object is fully initialized and the framework
862/// might call its [build] method any number of times to obtain a
863/// description of the user interface for this subtree. [State] objects can
864/// spontaneously request to rebuild their subtree by calling their
865/// [setState] method, which indicates that some of their internal state
866/// has changed in a way that might impact the user interface in this
867/// subtree.
868/// * During this time, a parent widget might rebuild and request that this
869/// location in the tree update to display a new widget with the same
870/// [runtimeType] and [Widget.key]. When this happens, the framework will
871/// update the [widget] property to refer to the new widget and then call the
872/// [didUpdateWidget] method with the previous widget as an argument. [State]
873/// objects should override [didUpdateWidget] to respond to changes in their
874/// associated widget (e.g., to start implicit animations). The framework
875/// always calls [build] after calling [didUpdateWidget], which means any
876/// calls to [setState] in [didUpdateWidget] are redundant. (See also the
877/// discussion at [Element.rebuild].)
878/// * During development, if a hot reload occurs (whether initiated from the
879/// command line `flutter` tool by pressing `r`, or from an IDE), the
880/// [reassemble] method is called. This provides an opportunity to
881/// reinitialize any data that was prepared in the [initState] method.
882/// * If the subtree containing the [State] object is removed from the tree
883/// (e.g., because the parent built a widget with a different [runtimeType]
884/// or [Widget.key]), the framework calls the [deactivate] method. Subclasses
885/// should override this method to clean up any links between this object
886/// and other elements in the tree (e.g. if you have provided an ancestor
887/// with a pointer to a descendant's [RenderObject]).
888/// * At this point, the framework might reinsert this subtree into another
889/// part of the tree. If that happens, the framework will ensure that it
890/// calls [build] to give the [State] object a chance to adapt to its new
891/// location in the tree. If the framework does reinsert this subtree, it
892/// will do so before the end of the animation frame in which the subtree was
893/// removed from the tree. For this reason, [State] objects can defer
894/// releasing most resources until the framework calls their [dispose]
895/// method.
896/// * If the framework does not reinsert this subtree by the end of the current
897/// animation frame, the framework will call [dispose], which indicates that
898/// this [State] object will never build again. Subclasses should override
899/// this method to release any resources retained by this object (e.g.,
900/// stop any active animations).
901/// * After the framework calls [dispose], the [State] object is considered
902/// unmounted and the [mounted] property is false. It is an error to call
903/// [setState] at this point. This stage of the lifecycle is terminal: there
904/// is no way to remount a [State] object that has been disposed.
905///
906/// See also:
907///
908/// * [StatefulWidget], where the current configuration of a [State] is hosted,
909/// and whose documentation has sample code for [State].
910/// * [StatelessWidget], for widgets that always build the same way given a
911/// particular configuration and ambient state.
912/// * [InheritedWidget], for widgets that introduce ambient state that can
913/// be read by descendant widgets.
914/// * [Widget], for an overview of widgets in general.
915@optionalTypeArgs
916abstract class State<T extends StatefulWidget> with Diagnosticable {
917 /// The current configuration.
918 ///
919 /// A [State] object's configuration is the corresponding [StatefulWidget]
920 /// instance. This property is initialized by the framework before calling
921 /// [initState]. If the parent updates this location in the tree to a new
922 /// widget with the same [runtimeType] and [Widget.key] as the current
923 /// configuration, the framework will update this property to refer to the new
924 /// widget and then call [didUpdateWidget], passing the old configuration as
925 /// an argument.
926 T get widget => _widget!;
927 T? _widget;
928
929 /// The current stage in the lifecycle for this state object.
930 ///
931 /// This field is used by the framework when asserts are enabled to verify
932 /// that [State] objects move through their lifecycle in an orderly fashion.
933 _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
934
935 /// Verifies that the [State] that was created is one that expects to be
936 /// created for that particular [Widget].
937 bool _debugTypesAreRight(Widget widget) => widget is T;
938
939 /// The location in the tree where this widget builds.
940 ///
941 /// The framework associates [State] objects with a [BuildContext] after
942 /// creating them with [StatefulWidget.createState] and before calling
943 /// [initState]. The association is permanent: the [State] object will never
944 /// change its [BuildContext]. However, the [BuildContext] itself can be moved
945 /// around the tree.
946 ///
947 /// After calling [dispose], the framework severs the [State] object's
948 /// connection with the [BuildContext].
949 BuildContext get context {
950 assert(() {
951 if (_element == null) {
952 throw FlutterError(
953 'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
954 'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
955 );
956 }
957 return true;
958 }());
959 return _element!;
960 }
961
962 StatefulElement? _element;
963
964 /// Whether this [State] object is currently in a tree.
965 ///
966 /// After creating a [State] object and before calling [initState], the
967 /// framework "mounts" the [State] object by associating it with a
968 /// [BuildContext]. The [State] object remains mounted until the framework
969 /// calls [dispose], after which time the framework will never ask the [State]
970 /// object to [build] again.
971 ///
972 /// It is an error to call [setState] unless [mounted] is true.
973 bool get mounted => _element != null;
974
975 /// Called when this object is inserted into the tree.
976 ///
977 /// The framework will call this method exactly once for each [State] object
978 /// it creates.
979 ///
980 /// Override this method to perform initialization that depends on the
981 /// location at which this object was inserted into the tree (i.e., [context])
982 /// or on the widget used to configure this object (i.e., [widget]).
983 ///
984 /// {@template flutter.widgets.State.initState}
985 /// If a [State]'s [build] method depends on an object that can itself
986 /// change state, for example a [ChangeNotifier] or [Stream], or some
987 /// other object to which one can subscribe to receive notifications, then
988 /// be sure to subscribe and unsubscribe properly in [initState],
989 /// [didUpdateWidget], and [dispose]:
990 ///
991 /// * In [initState], subscribe to the object.
992 /// * In [didUpdateWidget] unsubscribe from the old object and subscribe
993 /// to the new one if the updated widget configuration requires
994 /// replacing the object.
995 /// * In [dispose], unsubscribe from the object.
996 ///
997 /// {@endtemplate}
998 ///
999 /// You should not use [BuildContext.dependOnInheritedWidgetOfExactType] from this
1000 /// method. However, [didChangeDependencies] will be called immediately
1001 /// following this method, and [BuildContext.dependOnInheritedWidgetOfExactType] can
1002 /// be used there.
1003 ///
1004 /// Implementations of this method should start with a call to the inherited
1005 /// method, as in `super.initState()`.
1006 @protected
1007 @mustCallSuper
1008 void initState() {
1009 assert(_debugLifecycleState == _StateLifecycle.created);
1010 assert(debugMaybeDispatchCreated('widgets', 'State', this));
1011 }
1012
1013 /// Called whenever the widget configuration changes.
1014 ///
1015 /// If the parent widget rebuilds and requests that this location in the tree
1016 /// update to display a new widget with the same [runtimeType] and
1017 /// [Widget.key], the framework will update the [widget] property of this
1018 /// [State] object to refer to the new widget and then call this method
1019 /// with the previous widget as an argument.
1020 ///
1021 /// Override this method to respond when the [widget] changes (e.g., to start
1022 /// implicit animations).
1023 ///
1024 /// The framework always calls [build] after calling [didUpdateWidget], which
1025 /// means any calls to [setState] in [didUpdateWidget] are redundant.
1026 ///
1027 /// {@macro flutter.widgets.State.initState}
1028 ///
1029 /// Implementations of this method should start with a call to the inherited
1030 /// method, as in `super.didUpdateWidget(oldWidget)`.
1031 ///
1032 /// _See the discussion at [Element.rebuild] for more information on when this
1033 /// method is called._
1034 @mustCallSuper
1035 @protected
1036 void didUpdateWidget(covariant T oldWidget) {}
1037
1038 /// {@macro flutter.widgets.Element.reassemble}
1039 ///
1040 /// In addition to this method being invoked, it is guaranteed that the
1041 /// [build] method will be invoked when a reassemble is signaled. Most
1042 /// widgets therefore do not need to do anything in the [reassemble] method.
1043 ///
1044 /// See also:
1045 ///
1046 /// * [Element.reassemble]
1047 /// * [BindingBase.reassembleApplication]
1048 /// * [Image], which uses this to reload images.
1049 @protected
1050 @mustCallSuper
1051 void reassemble() {}
1052
1053 /// Notify the framework that the internal state of this object has changed.
1054 ///
1055 /// Whenever you change the internal state of a [State] object, make the
1056 /// change in a function that you pass to [setState]:
1057 ///
1058 /// ```dart
1059 /// setState(() { _myState = newValue; });
1060 /// ```
1061 ///
1062 /// The provided callback is immediately called synchronously. It must not
1063 /// return a future (the callback cannot be `async`), since then it would be
1064 /// unclear when the state was actually being set.
1065 ///
1066 /// Calling [setState] notifies the framework that the internal state of this
1067 /// object has changed in a way that might impact the user interface in this
1068 /// subtree, which causes the framework to schedule a [build] for this [State]
1069 /// object.
1070 ///
1071 /// If you just change the state directly without calling [setState], the
1072 /// framework might not schedule a [build] and the user interface for this
1073 /// subtree might not be updated to reflect the new state.
1074 ///
1075 /// Generally it is recommended that the [setState] method only be used to
1076 /// wrap the actual changes to the state, not any computation that might be
1077 /// associated with the change. For example, here a value used by the [build]
1078 /// function is incremented, and then the change is written to disk, but only
1079 /// the increment is wrapped in the [setState]:
1080 ///
1081 /// ```dart
1082 /// Future<void> _incrementCounter() async {
1083 /// setState(() {
1084 /// _counter++;
1085 /// });
1086 /// Directory directory = await getApplicationDocumentsDirectory(); // from path_provider package
1087 /// final String dirName = directory.path;
1088 /// await File('$dirName/counter.txt').writeAsString('$_counter');
1089 /// }
1090 /// ```
1091 ///
1092 /// Sometimes, the changed state is in some other object not owned by the
1093 /// widget [State], but the widget nonetheless needs to be updated to react to
1094 /// the new state. This is especially common with [Listenable]s, such as
1095 /// [AnimationController]s.
1096 ///
1097 /// In such cases, it is good practice to leave a comment in the callback
1098 /// passed to [setState] that explains what state changed:
1099 ///
1100 /// ```dart
1101 /// void _update() {
1102 /// setState(() { /* The animation changed. */ });
1103 /// }
1104 /// //...
1105 /// animation.addListener(_update);
1106 /// ```
1107 ///
1108 /// It is an error to call this method after the framework calls [dispose].
1109 /// You can determine whether it is legal to call this method by checking
1110 /// whether the [mounted] property is true. That said, it is better practice
1111 /// to cancel whatever work might trigger the [setState] rather than merely
1112 /// checking for [mounted] before calling [setState], as otherwise CPU cycles
1113 /// will be wasted.
1114 ///
1115 /// ## Design discussion
1116 ///
1117 /// The original version of this API was a method called `markNeedsBuild`, for
1118 /// consistency with [RenderObject.markNeedsLayout],
1119 /// [RenderObject.markNeedsPaint], _et al_.
1120 ///
1121 /// However, early user testing of the Flutter framework revealed that people
1122 /// would call `markNeedsBuild()` much more often than necessary. Essentially,
1123 /// people used it like a good luck charm, any time they weren't sure if they
1124 /// needed to call it, they would call it, just in case.
1125 ///
1126 /// Naturally, this led to performance issues in applications.
1127 ///
1128 /// When the API was changed to take a callback instead, this practice was
1129 /// greatly reduced. One hypothesis is that prompting developers to actually
1130 /// update their state in a callback caused developers to think more carefully
1131 /// about what exactly was being updated, and thus improved their understanding
1132 /// of the appropriate times to call the method.
1133 ///
1134 /// In practice, the [setState] method's implementation is trivial: it calls
1135 /// the provided callback synchronously, then calls [Element.markNeedsBuild].
1136 ///
1137 /// ## Performance considerations
1138 ///
1139 /// There is minimal _direct_ overhead to calling this function, and as it is
1140 /// expected to be called at most once per frame, the overhead is irrelevant
1141 /// anyway. Nonetheless, it is best to avoid calling this function redundantly
1142 /// (e.g. in a tight loop), as it does involve creating a closure and calling
1143 /// it. The method is idempotent, there is no benefit to calling it more than
1144 /// once per [State] per frame.
1145 ///
1146 /// The _indirect_ cost of causing this function, however, is high: it causes
1147 /// the widget to rebuild, possibly triggering rebuilds for the entire subtree
1148 /// rooted at this widget, and further triggering a relayout and repaint of
1149 /// the entire corresponding [RenderObject] subtree.
1150 ///
1151 /// For this reason, this method should only be called when the [build] method
1152 /// will, as a result of whatever state change was detected, change its result
1153 /// meaningfully.
1154 ///
1155 /// See also:
1156 ///
1157 /// * [StatefulWidget], the API documentation for which has a section on
1158 /// performance considerations that are relevant here.
1159 @protected
1160 void setState(VoidCallback fn) {
1161 assert(() {
1162 if (_debugLifecycleState == _StateLifecycle.defunct) {
1163 throw FlutterError.fromParts(<DiagnosticsNode>[
1164 ErrorSummary('setState() called after dispose(): $this'),
1165 ErrorDescription(
1166 'This error happens if you call setState() on a State object for a widget that '
1167 'no longer appears in the widget tree (e.g., whose parent widget no longer '
1168 'includes the widget in its build). This error can occur when code calls '
1169 'setState() from a timer or an animation callback.',
1170 ),
1171 ErrorHint(
1172 'The preferred solution is '
1173 'to cancel the timer or stop listening to the animation in the dispose() '
1174 'callback. Another solution is to check the "mounted" property of this '
1175 'object before calling setState() to ensure the object is still in the '
1176 'tree.',
1177 ),
1178 ErrorHint(
1179 'This error might indicate a memory leak if setState() is being called '
1180 'because another object is retaining a reference to this State object '
1181 'after it has been removed from the tree. To avoid memory leaks, '
1182 'consider breaking the reference to this object during dispose().',
1183 ),
1184 ]);
1185 }
1186 if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
1187 throw FlutterError.fromParts(<DiagnosticsNode>[
1188 ErrorSummary('setState() called in constructor: $this'),
1189 ErrorHint(
1190 'This happens when you call setState() on a State object for a widget that '
1191 "hasn't been inserted into the widget tree yet. It is not necessary to call "
1192 'setState() in the constructor, since the state is already assumed to be dirty '
1193 'when it is initially created.',
1194 ),
1195 ]);
1196 }
1197 return true;
1198 }());
1199 final Object? result = fn() as dynamic;
1200 assert(() {
1201 if (result is Future) {
1202 throw FlutterError.fromParts(<DiagnosticsNode>[
1203 ErrorSummary('setState() callback argument returned a Future.'),
1204 ErrorDescription(
1205 'The setState() method on $this was called with a closure or method that '
1206 'returned a Future. Maybe it is marked as "async".',
1207 ),
1208 ErrorHint(
1209 'Instead of performing asynchronous work inside a call to setState(), first '
1210 'execute the work (without updating the widget state), and then synchronously '
1211 'update the state inside a call to setState().',
1212 ),
1213 ]);
1214 }
1215 // We ignore other types of return values so that you can do things like:
1216 // setState(() => x = 3);
1217 return true;
1218 }());
1219 _element!.markNeedsBuild();
1220 }
1221
1222 /// Called when this object is removed from the tree.
1223 ///
1224 /// The framework calls this method whenever it removes this [State] object
1225 /// from the tree. In some cases, the framework will reinsert the [State]
1226 /// object into another part of the tree (e.g., if the subtree containing this
1227 /// [State] object is grafted from one location in the tree to another due to
1228 /// the use of a [GlobalKey]). If that happens, the framework will call
1229 /// [activate] to give the [State] object a chance to reacquire any resources
1230 /// that it released in [deactivate]. It will then also call [build] to give
1231 /// the [State] object a chance to adapt to its new location in the tree. If
1232 /// the framework does reinsert this subtree, it will do so before the end of
1233 /// the animation frame in which the subtree was removed from the tree. For
1234 /// this reason, [State] objects can defer releasing most resources until the
1235 /// framework calls their [dispose] method.
1236 ///
1237 /// Subclasses should override this method to clean up any links between
1238 /// this object and other elements in the tree (e.g. if you have provided an
1239 /// ancestor with a pointer to a descendant's [RenderObject]).
1240 ///
1241 /// Implementations of this method should end with a call to the inherited
1242 /// method, as in `super.deactivate()`.
1243 ///
1244 /// See also:
1245 ///
1246 /// * [dispose], which is called after [deactivate] if the widget is removed
1247 /// from the tree permanently.
1248 @protected
1249 @mustCallSuper
1250 void deactivate() {}
1251
1252 /// Called when this object is reinserted into the tree after having been
1253 /// removed via [deactivate].
1254 ///
1255 /// In most cases, after a [State] object has been deactivated, it is _not_
1256 /// reinserted into the tree, and its [dispose] method will be called to
1257 /// signal that it is ready to be garbage collected.
1258 ///
1259 /// In some cases, however, after a [State] object has been deactivated, the
1260 /// framework will reinsert it into another part of the tree (e.g., if the
1261 /// subtree containing this [State] object is grafted from one location in
1262 /// the tree to another due to the use of a [GlobalKey]). If that happens,
1263 /// the framework will call [activate] to give the [State] object a chance to
1264 /// reacquire any resources that it released in [deactivate]. It will then
1265 /// also call [build] to give the object a chance to adapt to its new
1266 /// location in the tree. If the framework does reinsert this subtree, it
1267 /// will do so before the end of the animation frame in which the subtree was
1268 /// removed from the tree. For this reason, [State] objects can defer
1269 /// releasing most resources until the framework calls their [dispose] method.
1270 ///
1271 /// The framework does not call this method the first time a [State] object
1272 /// is inserted into the tree. Instead, the framework calls [initState] in
1273 /// that situation.
1274 ///
1275 /// Implementations of this method should start with a call to the inherited
1276 /// method, as in `super.activate()`.
1277 ///
1278 /// See also:
1279 ///
1280 /// * [Element.activate], the corresponding method when an element
1281 /// transitions from the "inactive" to the "active" lifecycle state.
1282 @protected
1283 @mustCallSuper
1284 void activate() {}
1285
1286 /// Called when this object is removed from the tree permanently.
1287 ///
1288 /// The framework calls this method when this [State] object will never
1289 /// build again. After the framework calls [dispose], the [State] object is
1290 /// considered unmounted and the [mounted] property is false. It is an error
1291 /// to call [setState] at this point. This stage of the lifecycle is terminal:
1292 /// there is no way to remount a [State] object that has been disposed.
1293 ///
1294 /// Subclasses should override this method to release any resources retained
1295 /// by this object (e.g., stop any active animations).
1296 ///
1297 /// {@macro flutter.widgets.State.initState}
1298 ///
1299 /// Implementations of this method should end with a call to the inherited
1300 /// method, as in `super.dispose()`.
1301 ///
1302 /// ## Caveats
1303 ///
1304 /// This method is _not_ invoked at times where a developer might otherwise
1305 /// expect it, such as application shutdown or dismissal via platform
1306 /// native methods.
1307 ///
1308 /// ### Application shutdown
1309 ///
1310 /// There is no way to predict when application shutdown will happen. For
1311 /// example, a user's battery could catch fire, or the user could drop the
1312 /// device into a swimming pool, or the operating system could unilaterally
1313 /// terminate the application process due to memory pressure.
1314 ///
1315 /// Applications are responsible for ensuring that they are well-behaved
1316 /// even in the face of a rapid unscheduled termination.
1317 ///
1318 /// To artificially cause the entire widget tree to be disposed, consider
1319 /// calling [runApp] with a widget such as [SizedBox.shrink].
1320 ///
1321 /// To listen for platform shutdown messages (and other lifecycle changes),
1322 /// consider the [AppLifecycleListener] API.
1323 ///
1324 /// {@macro flutter.widgets.runApp.dismissal}
1325 ///
1326 /// See the method used to bootstrap the app (e.g. [runApp] or [runWidget])
1327 /// for suggestions on how to release resources more eagerly.
1328 ///
1329 /// See also:
1330 ///
1331 /// * [deactivate], which is called prior to [dispose].
1332 @protected
1333 @mustCallSuper
1334 void dispose() {
1335 assert(_debugLifecycleState == _StateLifecycle.ready);
1336 assert(() {
1337 _debugLifecycleState = _StateLifecycle.defunct;
1338 return true;
1339 }());
1340 assert(debugMaybeDispatchDisposed(this));
1341 }
1342
1343 /// Describes the part of the user interface represented by this widget.
1344 ///
1345 /// The framework calls this method in a number of different situations. For
1346 /// example:
1347 ///
1348 /// * After calling [initState].
1349 /// * After calling [didUpdateWidget].
1350 /// * After receiving a call to [setState].
1351 /// * After a dependency of this [State] object changes (e.g., an
1352 /// [InheritedWidget] referenced by the previous [build] changes).
1353 /// * After calling [deactivate] and then reinserting the [State] object into
1354 /// the tree at another location.
1355 ///
1356 /// This method can potentially be called in every frame and should not have
1357 /// any side effects beyond building a widget.
1358 ///
1359 /// The framework replaces the subtree below this widget with the widget
1360 /// returned by this method, either by updating the existing subtree or by
1361 /// removing the subtree and inflating a new subtree, depending on whether the
1362 /// widget returned by this method can update the root of the existing
1363 /// subtree, as determined by calling [Widget.canUpdate].
1364 ///
1365 /// Typically implementations return a newly created constellation of widgets
1366 /// that are configured with information from this widget's constructor, the
1367 /// given [BuildContext], and the internal state of this [State] object.
1368 ///
1369 /// The given [BuildContext] contains information about the location in the
1370 /// tree at which this widget is being built. For example, the context
1371 /// provides the set of inherited widgets for this location in the tree. The
1372 /// [BuildContext] argument is always the same as the [context] property of
1373 /// this [State] object and will remain the same for the lifetime of this
1374 /// object. The [BuildContext] argument is provided redundantly here so that
1375 /// this method matches the signature for a [WidgetBuilder].
1376 ///
1377 /// ## Design discussion
1378 ///
1379 /// ### Why is the [build] method on [State], and not [StatefulWidget]?
1380 ///
1381 /// Putting a `Widget build(BuildContext context)` method on [State] rather
1382 /// than putting a `Widget build(BuildContext context, State state)` method
1383 /// on [StatefulWidget] gives developers more flexibility when subclassing
1384 /// [StatefulWidget].
1385 ///
1386 /// For example, [AnimatedWidget] is a subclass of [StatefulWidget] that
1387 /// introduces an abstract `Widget build(BuildContext context)` method for its
1388 /// subclasses to implement. If [StatefulWidget] already had a [build] method
1389 /// that took a [State] argument, [AnimatedWidget] would be forced to provide
1390 /// its [State] object to subclasses even though its [State] object is an
1391 /// internal implementation detail of [AnimatedWidget].
1392 ///
1393 /// Conceptually, [StatelessWidget] could also be implemented as a subclass of
1394 /// [StatefulWidget] in a similar manner. If the [build] method were on
1395 /// [StatefulWidget] rather than [State], that would not be possible anymore.
1396 ///
1397 /// Putting the [build] function on [State] rather than [StatefulWidget] also
1398 /// helps avoid a category of bugs related to closures implicitly capturing
1399 /// `this`. If you defined a closure in a [build] function on a
1400 /// [StatefulWidget], that closure would implicitly capture `this`, which is
1401 /// the current widget instance, and would have the (immutable) fields of that
1402 /// instance in scope:
1403 ///
1404 /// ```dart
1405 /// // (this is not valid Flutter code)
1406 /// class MyButton extends StatefulWidgetX {
1407 /// MyButton({super.key, required this.color});
1408 ///
1409 /// final Color color;
1410 ///
1411 /// @override
1412 /// Widget build(BuildContext context, State state) {
1413 /// return SpecialWidget(
1414 /// handler: () { print('color: $color'); },
1415 /// );
1416 /// }
1417 /// }
1418 /// ```
1419 ///
1420 /// For example, suppose the parent builds `MyButton` with `color` being blue,
1421 /// the `$color` in the print function refers to blue, as expected. Now,
1422 /// suppose the parent rebuilds `MyButton` with green. The closure created by
1423 /// the first build still implicitly refers to the original widget and the
1424 /// `$color` still prints blue even through the widget has been updated to
1425 /// green; should that closure outlive its widget, it would print outdated
1426 /// information.
1427 ///
1428 /// In contrast, with the [build] function on the [State] object, closures
1429 /// created during [build] implicitly capture the [State] instance instead of
1430 /// the widget instance:
1431 ///
1432 /// ```dart
1433 /// class MyButton extends StatefulWidget {
1434 /// const MyButton({super.key, this.color = Colors.teal});
1435 ///
1436 /// final Color color;
1437 /// // ...
1438 /// }
1439 ///
1440 /// class MyButtonState extends State<MyButton> {
1441 /// // ...
1442 /// @override
1443 /// Widget build(BuildContext context) {
1444 /// return SpecialWidget(
1445 /// handler: () { print('color: ${widget.color}'); },
1446 /// );
1447 /// }
1448 /// }
1449 /// ```
1450 ///
1451 /// Now when the parent rebuilds `MyButton` with green, the closure created by
1452 /// the first build still refers to [State] object, which is preserved across
1453 /// rebuilds, but the framework has updated that [State] object's [widget]
1454 /// property to refer to the new `MyButton` instance and `${widget.color}`
1455 /// prints green, as expected.
1456 ///
1457 /// See also:
1458 ///
1459 /// * [StatefulWidget], which contains the discussion on performance considerations.
1460 @protected
1461 Widget build(BuildContext context);
1462
1463 /// Called when a dependency of this [State] object changes.
1464 ///
1465 /// For example, if the previous call to [build] referenced an
1466 /// [InheritedWidget] that later changed, the framework would call this
1467 /// method to notify this object about the change.
1468 ///
1469 /// This method is also called immediately after [initState]. It is safe to
1470 /// call [BuildContext.dependOnInheritedWidgetOfExactType] from this method.
1471 ///
1472 /// Subclasses rarely override this method because the framework always
1473 /// calls [build] after a dependency changes. Some subclasses do override
1474 /// this method because they need to do some expensive work (e.g., network
1475 /// fetches) when their dependencies change, and that work would be too
1476 /// expensive to do for every build.
1477 @protected
1478 @mustCallSuper
1479 void didChangeDependencies() {}
1480
1481 @override
1482 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
1483 super.debugFillProperties(properties);
1484 assert(() {
1485 properties.add(
1486 EnumProperty<_StateLifecycle>(
1487 'lifecycle state',
1488 _debugLifecycleState,
1489 defaultValue: _StateLifecycle.ready,
1490 ),
1491 );
1492 return true;
1493 }());
1494 properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
1495 properties.add(
1496 ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'),
1497 );
1498 }
1499
1500 // If @protected State methods are added or removed, the analysis rule should be
1501 // updated accordingly (dev/bots/custom_rules/protect_public_state_subtypes.dart)
1502}
1503
1504/// A widget that has a child widget provided to it, instead of building a new
1505/// widget.
1506///
1507/// Useful as a base class for other widgets, such as [InheritedWidget] and
1508/// [ParentDataWidget].
1509///
1510/// See also:
1511///
1512/// * [InheritedWidget], for widgets that introduce ambient state that can
1513/// be read by descendant widgets.
1514/// * [ParentDataWidget], for widgets that populate the
1515/// [RenderObject.parentData] slot of their child's [RenderObject] to
1516/// configure the parent widget's layout.
1517/// * [StatefulWidget] and [State], for widgets that can build differently
1518/// several times over their lifetime.
1519/// * [StatelessWidget], for widgets that always build the same way given a
1520/// particular configuration and ambient state.
1521/// * [Widget], for an overview of widgets in general.
1522abstract class ProxyWidget extends Widget {
1523 /// Creates a widget that has exactly one child widget.
1524 const ProxyWidget({super.key, required this.child});
1525
1526 /// The widget below this widget in the tree.
1527 ///
1528 /// {@template flutter.widgets.ProxyWidget.child}
1529 /// This widget can only have one child. To lay out multiple children, let this
1530 /// widget's child be a widget such as [Row], [Column], or [Stack], which have a
1531 /// `children` property, and then provide the children to that widget.
1532 /// {@endtemplate}
1533 final Widget child;
1534}
1535
1536/// Base class for widgets that hook [ParentData] information to children of
1537/// [RenderObjectWidget]s.
1538///
1539/// This can be used to provide per-child configuration for
1540/// [RenderObjectWidget]s with more than one child. For example, [Stack] uses
1541/// the [Positioned] parent data widget to position each child.
1542///
1543/// A [ParentDataWidget] is specific to a particular kind of [ParentData]. That
1544/// class is `T`, the [ParentData] type argument.
1545///
1546/// {@tool snippet}
1547///
1548/// This example shows how you would build a [ParentDataWidget] to configure a
1549/// `FrogJar` widget's children by specifying a [Size] for each one.
1550///
1551/// ```dart
1552/// class FrogSize extends ParentDataWidget<FrogJarParentData> {
1553/// const FrogSize({
1554/// super.key,
1555/// required this.size,
1556/// required super.child,
1557/// });
1558///
1559/// final Size size;
1560///
1561/// @override
1562/// void applyParentData(RenderObject renderObject) {
1563/// final FrogJarParentData parentData = renderObject.parentData! as FrogJarParentData;
1564/// if (parentData.size != size) {
1565/// parentData.size = size;
1566/// final RenderFrogJar targetParent = renderObject.parent! as RenderFrogJar;
1567/// targetParent.markNeedsLayout();
1568/// }
1569/// }
1570///
1571/// @override
1572/// Type get debugTypicalAncestorWidgetClass => FrogJar;
1573/// }
1574/// ```
1575/// {@end-tool}
1576///
1577/// See also:
1578///
1579/// * [RenderObject], the superclass for layout algorithms.
1580/// * [RenderObject.parentData], the slot that this class configures.
1581/// * [ParentData], the superclass of the data that will be placed in
1582/// [RenderObject.parentData] slots. The `T` type parameter for
1583/// [ParentDataWidget] is a [ParentData].
1584/// * [RenderObjectWidget], the class for widgets that wrap [RenderObject]s.
1585/// * [StatefulWidget] and [State], for widgets that can build differently
1586/// several times over their lifetime.
1587abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
1588 /// Abstract const constructor. This constructor enables subclasses to provide
1589 /// const constructors so that they can be used in const expressions.
1590 const ParentDataWidget({super.key, required super.child});
1591
1592 @override
1593 ParentDataElement<T> createElement() => ParentDataElement<T>(this);
1594
1595 /// Checks if this widget can apply its parent data to the provided
1596 /// `renderObject`.
1597 ///
1598 /// The [RenderObject.parentData] of the provided `renderObject` is
1599 /// typically set up by an ancestor [RenderObjectWidget] of the type returned
1600 /// by [debugTypicalAncestorWidgetClass].
1601 ///
1602 /// This is called just before [applyParentData] is invoked with the same
1603 /// [RenderObject] provided to that method.
1604 bool debugIsValidRenderObject(RenderObject renderObject) {
1605 assert(T != dynamic);
1606 assert(T != ParentData);
1607 return renderObject.parentData is T;
1608 }
1609
1610 /// Describes the [RenderObjectWidget] that is typically used to set up the
1611 /// [ParentData] that [applyParentData] will write to.
1612 ///
1613 /// This is only used in error messages to tell users what widget typically
1614 /// wraps this [ParentDataWidget] through
1615 /// [debugTypicalAncestorWidgetDescription].
1616 ///
1617 /// ## Implementations
1618 ///
1619 /// The returned Type should describe a subclass of `RenderObjectWidget`. If
1620 /// more than one Type is supported, use
1621 /// [debugTypicalAncestorWidgetDescription], which typically inserts this
1622 /// value but can be overridden to describe more than one Type.
1623 ///
1624 /// ```dart
1625 /// @override
1626 /// Type get debugTypicalAncestorWidgetClass => FrogJar;
1627 /// ```
1628 ///
1629 /// If the "typical" parent is generic (`Foo<T>`), consider specifying either
1630 /// a typical type argument (e.g. `Foo<int>` if `int` is typically how the
1631 /// type is specialized), or specifying the upper bound (e.g. `Foo<Object?>`).
1632 Type get debugTypicalAncestorWidgetClass;
1633
1634 /// Describes the [RenderObjectWidget] that is typically used to set up the
1635 /// [ParentData] that [applyParentData] will write to.
1636 ///
1637 /// This is only used in error messages to tell users what widget typically
1638 /// wraps this [ParentDataWidget].
1639 ///
1640 /// Returns [debugTypicalAncestorWidgetClass] by default as a String. This can
1641 /// be overridden to describe more than one Type of valid parent.
1642 String get debugTypicalAncestorWidgetDescription => '$debugTypicalAncestorWidgetClass';
1643
1644 Iterable<DiagnosticsNode> _debugDescribeIncorrectParentDataType({
1645 required ParentData? parentData,
1646 RenderObjectWidget? parentDataCreator,
1647 DiagnosticsNode? ownershipChain,
1648 }) {
1649 assert(T != dynamic);
1650 assert(T != ParentData);
1651
1652 final String description =
1653 'The ParentDataWidget $this wants to apply ParentData of type $T to a RenderObject';
1654 return <DiagnosticsNode>[
1655 if (parentData == null)
1656 ErrorDescription('$description, which has not been set up to receive any ParentData.')
1657 else
1658 ErrorDescription(
1659 '$description, which has been set up to accept ParentData of incompatible type ${parentData.runtimeType}.',
1660 ),
1661 ErrorHint(
1662 'Usually, this means that the $runtimeType widget has the wrong ancestor RenderObjectWidget. '
1663 'Typically, $runtimeType widgets are placed directly inside $debugTypicalAncestorWidgetDescription widgets.',
1664 ),
1665 if (parentDataCreator != null)
1666 ErrorHint(
1667 'The offending $runtimeType is currently placed inside a ${parentDataCreator.runtimeType} widget.',
1668 ),
1669 if (ownershipChain != null)
1670 ErrorDescription(
1671 'The ownership chain for the RenderObject that received the incompatible parent data was:\n $ownershipChain',
1672 ),
1673 ];
1674 }
1675
1676 /// Write the data from this widget into the given render object's parent data.
1677 ///
1678 /// The framework calls this function whenever it detects that the
1679 /// [RenderObject] associated with the [child] has outdated
1680 /// [RenderObject.parentData]. For example, if the render object was recently
1681 /// inserted into the render tree, the render object's parent data might not
1682 /// match the data in this widget.
1683 ///
1684 /// Subclasses are expected to override this function to copy data from their
1685 /// fields into the [RenderObject.parentData] field of the given render
1686 /// object. The render object's parent is guaranteed to have been created by a
1687 /// widget of type `T`, which usually means that this function can assume that
1688 /// the render object's parent data object inherits from a particular class.
1689 ///
1690 /// If this function modifies data that can change the parent's layout or
1691 /// painting, this function is responsible for calling
1692 /// [RenderObject.markNeedsLayout] or [RenderObject.markNeedsPaint] on the
1693 /// parent, as appropriate.
1694 @protected
1695 void applyParentData(RenderObject renderObject);
1696
1697 /// Whether the [ParentDataElement.applyWidgetOutOfTurn] method is allowed
1698 /// with this widget.
1699 ///
1700 /// This should only return true if this widget represents a [ParentData]
1701 /// configuration that will have no impact on the layout or paint phase.
1702 ///
1703 /// See also:
1704 ///
1705 /// * [ParentDataElement.applyWidgetOutOfTurn], which verifies this in debug
1706 /// mode.
1707 @protected
1708 bool debugCanApplyOutOfTurn() => false;
1709}
1710
1711/// Base class for widgets that efficiently propagate information down the tree.
1712///
1713/// {@youtube 560 315 https://www.youtube.com/watch?v=og-vJqLzg2c}
1714///
1715/// To obtain the nearest instance of a particular type of inherited widget from
1716/// a build context, use [BuildContext.dependOnInheritedWidgetOfExactType].
1717///
1718/// Inherited widgets, when referenced in this way, will cause the consumer to
1719/// rebuild when the inherited widget itself changes state.
1720///
1721/// {@youtube 560 315 https://www.youtube.com/watch?v=Zbm3hjPjQMk}
1722///
1723/// {@tool snippet}
1724///
1725/// The following is a skeleton of an inherited widget called `FrogColor`:
1726///
1727/// ```dart
1728/// class FrogColor extends InheritedWidget {
1729/// const FrogColor({
1730/// super.key,
1731/// required this.color,
1732/// required super.child,
1733/// });
1734///
1735/// final Color color;
1736///
1737/// static FrogColor? maybeOf(BuildContext context) {
1738/// return context.dependOnInheritedWidgetOfExactType<FrogColor>();
1739/// }
1740///
1741/// static FrogColor of(BuildContext context) {
1742/// final FrogColor? result = maybeOf(context);
1743/// assert(result != null, 'No FrogColor found in context');
1744/// return result!;
1745/// }
1746///
1747/// @override
1748/// bool updateShouldNotify(FrogColor oldWidget) => color != oldWidget.color;
1749/// }
1750/// ```
1751/// {@end-tool}
1752///
1753/// ## Implementing the `of` and `maybeOf` methods
1754///
1755/// The convention is to provide two static methods, `of` and `maybeOf`, on the
1756/// [InheritedWidget] which call
1757/// [BuildContext.dependOnInheritedWidgetOfExactType]. This allows the class to
1758/// define its own fallback logic in case there isn't a widget in scope.
1759///
1760/// The `of` method typically returns a non-nullable instance and asserts if the
1761/// [InheritedWidget] isn't found, and the `maybeOf` method returns a nullable
1762/// instance, and returns null if the [InheritedWidget] isn't found. The `of`
1763/// method is typically implemented by calling `maybeOf` internally.
1764///
1765/// Sometimes, the `of` and `maybeOf` methods return some data rather than the
1766/// inherited widget itself; for example, in this case it could have returned a
1767/// [Color] instead of the `FrogColor` widget.
1768///
1769/// Occasionally, the inherited widget is an implementation detail of another
1770/// class, and is therefore private. The `of` and `maybeOf` methods in that case
1771/// are typically implemented on the public class instead. For example, [Theme]
1772/// is implemented as a [StatelessWidget] that builds a private inherited
1773/// widget; [Theme.of] looks for that private inherited widget using
1774/// [BuildContext.dependOnInheritedWidgetOfExactType] and then returns the
1775/// [ThemeData] inside it.
1776///
1777/// ## Calling the `of` or `maybeOf` methods
1778///
1779/// When using the `of` or `maybeOf` methods, the `context` must be a descendant
1780/// of the [InheritedWidget], meaning it must be "below" the [InheritedWidget]
1781/// in the tree.
1782///
1783/// {@tool snippet}
1784///
1785/// In this example, the `context` used is the one from the [Builder], which is
1786/// a child of the `FrogColor` widget, so this works.
1787///
1788/// ```dart
1789/// // continuing from previous example...
1790/// class MyPage extends StatelessWidget {
1791/// const MyPage({super.key});
1792///
1793/// @override
1794/// Widget build(BuildContext context) {
1795/// return Scaffold(
1796/// body: FrogColor(
1797/// color: Colors.green,
1798/// child: Builder(
1799/// builder: (BuildContext innerContext) {
1800/// return Text(
1801/// 'Hello Frog',
1802/// style: TextStyle(color: FrogColor.of(innerContext).color),
1803/// );
1804/// },
1805/// ),
1806/// ),
1807/// );
1808/// }
1809/// }
1810/// ```
1811/// {@end-tool}
1812///
1813/// {@tool snippet}
1814///
1815/// In this example, the `context` used is the one from the `MyOtherPage`
1816/// widget, which is a parent of the `FrogColor` widget, so this does not work,
1817/// and will assert when `FrogColor.of` is called.
1818///
1819/// ```dart
1820/// // continuing from previous example...
1821///
1822/// class MyOtherPage extends StatelessWidget {
1823/// const MyOtherPage({super.key});
1824///
1825/// @override
1826/// Widget build(BuildContext context) {
1827/// return Scaffold(
1828/// body: FrogColor(
1829/// color: Colors.green,
1830/// child: Text(
1831/// 'Hello Frog',
1832/// style: TextStyle(color: FrogColor.of(context).color),
1833/// ),
1834/// ),
1835/// );
1836/// }
1837/// }
1838/// ```
1839/// {@end-tool} {@youtube 560 315 https://www.youtube.com/watch?v=1t-8rBCGBYw}
1840///
1841/// See also:
1842///
1843/// * [StatefulWidget] and [State], for widgets that can build differently
1844/// several times over their lifetime.
1845/// * [StatelessWidget], for widgets that always build the same way given a
1846/// particular configuration and ambient state.
1847/// * [Widget], for an overview of widgets in general.
1848/// * [InheritedNotifier], an inherited widget whose value can be a
1849/// [Listenable], and which will notify dependents whenever the value sends
1850/// notifications.
1851/// * [InheritedModel], an inherited widget that allows clients to subscribe to
1852/// changes for subparts of the value.
1853abstract class InheritedWidget extends ProxyWidget {
1854 /// Abstract const constructor. This constructor enables subclasses to provide
1855 /// const constructors so that they can be used in const expressions.
1856 const InheritedWidget({super.key, required super.child});
1857
1858 @override
1859 InheritedElement createElement() => InheritedElement(this);
1860
1861 /// Whether the framework should notify widgets that inherit from this widget.
1862 ///
1863 /// When this widget is rebuilt, sometimes we need to rebuild the widgets that
1864 /// inherit from this widget but sometimes we do not. For example, if the data
1865 /// held by this widget is the same as the data held by `oldWidget`, then we
1866 /// do not need to rebuild the widgets that inherited the data held by
1867 /// `oldWidget`.
1868 ///
1869 /// The framework distinguishes these cases by calling this function with the
1870 /// widget that previously occupied this location in the tree as an argument.
1871 /// The given widget is guaranteed to have the same [runtimeType] as this
1872 /// object.
1873 @protected
1874 bool updateShouldNotify(covariant InheritedWidget oldWidget);
1875}
1876
1877/// [RenderObjectWidget]s provide the configuration for [RenderObjectElement]s,
1878/// which wrap [RenderObject]s, which provide the actual rendering of the
1879/// application.
1880///
1881/// Usually, rather than subclassing [RenderObjectWidget] directly, render
1882/// object widgets subclass one of:
1883///
1884/// * [LeafRenderObjectWidget], if the widget has no children.
1885/// * [SingleChildRenderObjectWidget], if the widget has exactly one child.
1886/// * [MultiChildRenderObjectWidget], if the widget takes a list of children.
1887/// * [SlottedMultiChildRenderObjectWidget], if the widget organizes its
1888/// children in different named slots.
1889///
1890/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1891abstract class RenderObjectWidget extends Widget {
1892 /// Abstract const constructor. This constructor enables subclasses to provide
1893 /// const constructors so that they can be used in const expressions.
1894 const RenderObjectWidget({super.key});
1895
1896 /// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
1897 @override
1898 @factory
1899 RenderObjectElement createElement();
1900
1901 /// Creates an instance of the [RenderObject] class that this
1902 /// [RenderObjectWidget] represents, using the configuration described by this
1903 /// [RenderObjectWidget].
1904 ///
1905 /// This method should not do anything with the children of the render object.
1906 /// That should instead be handled by the method that overrides
1907 /// [RenderObjectElement.mount] in the object rendered by this object's
1908 /// [createElement] method. See, for example,
1909 /// [SingleChildRenderObjectElement.mount].
1910 @protected
1911 @factory
1912 RenderObject createRenderObject(BuildContext context);
1913
1914 /// Copies the configuration described by this [RenderObjectWidget] to the
1915 /// given [RenderObject], which will be of the same type as returned by this
1916 /// object's [createRenderObject].
1917 ///
1918 /// This method should not do anything to update the children of the render
1919 /// object. That should instead be handled by the method that overrides
1920 /// [RenderObjectElement.update] in the object rendered by this object's
1921 /// [createElement] method. See, for example,
1922 /// [SingleChildRenderObjectElement.update].
1923 @protected
1924 void updateRenderObject(BuildContext context, covariant RenderObject renderObject) {}
1925
1926 /// This method is called when a RenderObject that was previously
1927 /// associated with this widget is removed from the render tree.
1928 /// The provided [RenderObject] will be of the same type as the one created by
1929 /// this widget's [createRenderObject] method.
1930 @protected
1931 void didUnmountRenderObject(covariant RenderObject renderObject) {}
1932}
1933
1934/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1935/// that have no children.
1936///
1937/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1938abstract class LeafRenderObjectWidget extends RenderObjectWidget {
1939 /// Abstract const constructor. This constructor enables subclasses to provide
1940 /// const constructors so that they can be used in const expressions.
1941 const LeafRenderObjectWidget({super.key});
1942
1943 @override
1944 LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
1945}
1946
1947/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1948/// that have a single child slot.
1949///
1950/// The render object assigned to this widget should make use of
1951/// [RenderObjectWithChildMixin] to implement a single-child model. The mixin
1952/// exposes a [RenderObjectWithChildMixin.child] property that allows retrieving
1953/// the render object belonging to the [child] widget.
1954///
1955/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1956abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
1957 /// Abstract const constructor. This constructor enables subclasses to provide
1958 /// const constructors so that they can be used in const expressions.
1959 const SingleChildRenderObjectWidget({super.key, this.child});
1960
1961 /// The widget below this widget in the tree.
1962 ///
1963 /// {@macro flutter.widgets.ProxyWidget.child}
1964 final Widget? child;
1965
1966 @override
1967 SingleChildRenderObjectElement createElement() => SingleChildRenderObjectElement(this);
1968}
1969
1970/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1971/// that have a single list of children. (This superclass only provides the
1972/// storage for that child list, it doesn't actually provide the updating
1973/// logic.)
1974///
1975/// Subclasses must use a [RenderObject] that mixes in
1976/// [ContainerRenderObjectMixin], which provides the necessary functionality to
1977/// visit the children of the container render object (the render object
1978/// belonging to the [children] widgets). Typically, subclasses will use a
1979/// [RenderBox] that mixes in both [ContainerRenderObjectMixin] and
1980/// [RenderBoxContainerDefaultsMixin].
1981///
1982/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1983///
1984/// See also:
1985///
1986/// * [Stack], which uses [MultiChildRenderObjectWidget].
1987/// * [RenderStack], for an example implementation of the associated render
1988/// object.
1989/// * [SlottedMultiChildRenderObjectWidget], which configures a
1990/// [RenderObject] that instead of having a single list of children organizes
1991/// its children in named slots.
1992abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
1993 /// Initializes fields for subclasses.
1994 const MultiChildRenderObjectWidget({super.key, this.children = const <Widget>[]});
1995
1996 /// The widgets below this widget in the tree.
1997 ///
1998 /// If this list is going to be mutated, it is usually wise to put a [Key] on
1999 /// each of the child widgets, so that the framework can match old
2000 /// configurations to new configurations and maintain the underlying render
2001 /// objects.
2002 ///
2003 /// Also, a [Widget] in Flutter is immutable, so directly modifying the
2004 /// [children] such as `someMultiChildRenderObjectWidget.children.add(...)` or
2005 /// as the example code below will result in incorrect behaviors. Whenever the
2006 /// children list is modified, a new list object should be provided.
2007 ///
2008 /// ```dart
2009 /// // This code is incorrect.
2010 /// class SomeWidgetState extends State<SomeWidget> {
2011 /// final List<Widget> _children = <Widget>[];
2012 ///
2013 /// void someHandler() {
2014 /// setState(() {
2015 /// _children.add(const ChildWidget());
2016 /// });
2017 /// }
2018 ///
2019 /// @override
2020 /// Widget build(BuildContext context) {
2021 /// // Reusing `List _children` here is problematic.
2022 /// return Row(children: _children);
2023 /// }
2024 /// }
2025 /// ```
2026 ///
2027 /// The following code corrects the problem mentioned above.
2028 ///
2029 /// ```dart
2030 /// class SomeWidgetState extends State<SomeWidget> {
2031 /// final List<Widget> _children = <Widget>[];
2032 ///
2033 /// void someHandler() {
2034 /// setState(() {
2035 /// // The key here allows Flutter to reuse the underlying render
2036 /// // objects even if the children list is recreated.
2037 /// _children.add(ChildWidget(key: UniqueKey()));
2038 /// });
2039 /// }
2040 ///
2041 /// @override
2042 /// Widget build(BuildContext context) {
2043 /// // Always create a new list of children as a Widget is immutable.
2044 /// return Row(children: _children.toList());
2045 /// }
2046 /// }
2047 /// ```
2048 final List<Widget> children;
2049
2050 @override
2051 MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
2052}
2053
2054// ELEMENTS
2055
2056enum _ElementLifecycle { initial, active, inactive, defunct }
2057
2058class _InactiveElements {
2059 bool _locked = false;
2060 final Set<Element> _elements = HashSet<Element>();
2061
2062 void _unmount(Element element) {
2063 assert(element._lifecycleState == _ElementLifecycle.inactive);
2064 assert(() {
2065 if (debugPrintGlobalKeyedWidgetLifecycle) {
2066 if (element.widget.key is GlobalKey) {
2067 debugPrint('Discarding $element from inactive elements list.');
2068 }
2069 }
2070 return true;
2071 }());
2072 element.visitChildren((Element child) {
2073 assert(child._parent == element);
2074 _unmount(child);
2075 });
2076 element.unmount();
2077 assert(element._lifecycleState == _ElementLifecycle.defunct);
2078 }
2079
2080 void _unmountAll() {
2081 _locked = true;
2082 final List<Element> elements = _elements.toList()..sort(Element._sort);
2083 _elements.clear();
2084 try {
2085 elements.reversed.forEach(_unmount);
2086 } finally {
2087 assert(_elements.isEmpty);
2088 _locked = false;
2089 }
2090 }
2091
2092 static void _deactivateRecursively(Element element) {
2093 assert(element._lifecycleState == _ElementLifecycle.active);
2094 element.deactivate();
2095 assert(element._lifecycleState == _ElementLifecycle.inactive);
2096 element.visitChildren(_deactivateRecursively);
2097 assert(() {
2098 element.debugDeactivated();
2099 return true;
2100 }());
2101 }
2102
2103 void add(Element element) {
2104 assert(!_locked);
2105 assert(!_elements.contains(element));
2106 assert(element._parent == null);
2107 if (element._lifecycleState == _ElementLifecycle.active) {
2108 _deactivateRecursively(element);
2109 }
2110 _elements.add(element);
2111 }
2112
2113 void remove(Element element) {
2114 assert(!_locked);
2115 assert(_elements.contains(element));
2116 assert(element._parent == null);
2117 _elements.remove(element);
2118 assert(element._lifecycleState != _ElementLifecycle.active);
2119 }
2120
2121 bool debugContains(Element element) {
2122 late bool result;
2123 assert(() {
2124 result = _elements.contains(element);
2125 return true;
2126 }());
2127 return result;
2128 }
2129}
2130
2131/// Signature for the callback to [BuildContext.visitChildElements].
2132///
2133/// The argument is the child being visited.
2134///
2135/// It is safe to call `element.visitChildElements` reentrantly within
2136/// this callback.
2137typedef ElementVisitor = void Function(Element element);
2138
2139/// Signature for the callback to [BuildContext.visitAncestorElements].
2140///
2141/// The argument is the ancestor being visited.
2142///
2143/// Return false to stop the walk.
2144typedef ConditionalElementVisitor = bool Function(Element element);
2145
2146/// A handle to the location of a widget in the widget tree.
2147///
2148/// This class presents a set of methods that can be used from
2149/// [StatelessWidget.build] methods and from methods on [State] objects.
2150///
2151/// [BuildContext] objects are passed to [WidgetBuilder] functions (such as
2152/// [StatelessWidget.build]), and are available from the [State.context] member.
2153/// Some static functions (e.g. [showDialog], [Theme.of], and so forth) also
2154/// take build contexts so that they can act on behalf of the calling widget, or
2155/// obtain data specifically for the given context.
2156///
2157/// Each widget has its own [BuildContext], which becomes the parent of the
2158/// widget returned by the [StatelessWidget.build] or [State.build] function.
2159/// (And similarly, the parent of any children for [RenderObjectWidget]s.)
2160///
2161/// In particular, this means that within a build method, the build context of
2162/// the widget of the build method is not the same as the build context of the
2163/// widgets returned by that build method. This can lead to some tricky cases.
2164/// For example, [Theme.of(context)] looks for the nearest enclosing [Theme] of
2165/// the given build context. If a build method for a widget Q includes a [Theme]
2166/// within its returned widget tree, and attempts to use [Theme.of] passing its
2167/// own context, the build method for Q will not find that [Theme] object. It
2168/// will instead find whatever [Theme] was an ancestor to the widget Q. If the
2169/// build context for a subpart of the returned tree is needed, a [Builder]
2170/// widget can be used: the build context passed to the [Builder.builder]
2171/// callback will be that of the [Builder] itself.
2172///
2173/// For example, in the following snippet, the [ScaffoldState.showBottomSheet]
2174/// method is called on the [Scaffold] widget that the build method itself
2175/// creates. If a [Builder] had not been used, and instead the `context`
2176/// argument of the build method itself had been used, no [Scaffold] would have
2177/// been found, and the [Scaffold.of] function would have returned null.
2178///
2179/// ```dart
2180/// @override
2181/// Widget build(BuildContext context) {
2182/// // here, Scaffold.of(context) returns null
2183/// return Scaffold(
2184/// appBar: AppBar(title: const Text('Demo')),
2185/// body: Builder(
2186/// builder: (BuildContext context) {
2187/// return TextButton(
2188/// child: const Text('BUTTON'),
2189/// onPressed: () {
2190/// Scaffold.of(context).showBottomSheet(
2191/// (BuildContext context) {
2192/// return Container(
2193/// alignment: Alignment.center,
2194/// height: 200,
2195/// color: Colors.amber,
2196/// child: Center(
2197/// child: Column(
2198/// mainAxisSize: MainAxisSize.min,
2199/// children: <Widget>[
2200/// const Text('BottomSheet'),
2201/// ElevatedButton(
2202/// child: const Text('Close BottomSheet'),
2203/// onPressed: () {
2204/// Navigator.pop(context);
2205/// },
2206/// )
2207/// ],
2208/// ),
2209/// ),
2210/// );
2211/// },
2212/// );
2213/// },
2214/// );
2215/// },
2216/// )
2217/// );
2218/// }
2219/// ```
2220///
2221/// The [BuildContext] for a particular widget can change location over time as
2222/// the widget is moved around the tree. Because of this, values returned from
2223/// the methods on this class should not be cached beyond the execution of a
2224/// single synchronous function.
2225///
2226/// {@youtube 560 315 https://www.youtube.com/watch?v=rIaaH87z1-g}
2227///
2228/// Avoid storing instances of [BuildContext]s because they may become invalid
2229/// if the widget they are associated with is unmounted from the widget tree.
2230/// {@template flutter.widgets.BuildContext.asynchronous_gap}
2231/// If a [BuildContext] is used across an asynchronous gap (i.e. after performing
2232/// an asynchronous operation), consider checking [mounted] to determine whether
2233/// the context is still valid before interacting with it:
2234///
2235/// ```dart
2236/// @override
2237/// Widget build(BuildContext context) {
2238/// return OutlinedButton(
2239/// onPressed: () async {
2240/// await Future<void>.delayed(const Duration(seconds: 1));
2241/// if (context.mounted) {
2242/// Navigator.of(context).pop();
2243/// }
2244/// },
2245/// child: const Text('Delayed pop'),
2246/// );
2247/// }
2248/// ```
2249/// {@endtemplate}
2250///
2251/// [BuildContext] objects are actually [Element] objects. The [BuildContext]
2252/// interface is used to discourage direct manipulation of [Element] objects.
2253abstract class BuildContext {
2254 /// The current configuration of the [Element] that is this [BuildContext].
2255 Widget get widget;
2256
2257 /// The [BuildOwner] for this context. The [BuildOwner] is in charge of
2258 /// managing the rendering pipeline for this context.
2259 BuildOwner? get owner;
2260
2261 /// Whether the [Widget] this context is associated with is currently
2262 /// mounted in the widget tree.
2263 ///
2264 /// Accessing the properties of the [BuildContext] or calling any methods on
2265 /// it is only valid while mounted is true. If mounted is false, assertions
2266 /// will trigger.
2267 ///
2268 /// Once unmounted, a given [BuildContext] will never become mounted again.
2269 ///
2270 /// {@macro flutter.widgets.BuildContext.asynchronous_gap}
2271 bool get mounted;
2272
2273 /// Whether the [widget] is currently updating the widget or render tree.
2274 ///
2275 /// For [StatefulWidget]s and [StatelessWidget]s this flag is true while
2276 /// their respective build methods are executing.
2277 /// [RenderObjectWidget]s set this to true while creating or configuring their
2278 /// associated [RenderObject]s.
2279 /// Other [Widget] types may set this to true for conceptually similar phases
2280 /// of their lifecycle.
2281 ///
2282 /// When this is true, it is safe for [widget] to establish a dependency to an
2283 /// [InheritedWidget] by calling [dependOnInheritedElement] or
2284 /// [dependOnInheritedWidgetOfExactType].
2285 ///
2286 /// Accessing this flag in release mode is not valid.
2287 bool get debugDoingBuild;
2288
2289 /// The current [RenderObject] for the widget. If the widget is a
2290 /// [RenderObjectWidget], this is the render object that the widget created
2291 /// for itself. Otherwise, it is the render object of the first descendant
2292 /// [RenderObjectWidget].
2293 ///
2294 /// This method will only return a valid result after the build phase is
2295 /// complete. It is therefore not valid to call this from a build method.
2296 /// It should only be called from interaction event handlers (e.g.
2297 /// gesture callbacks) or layout or paint callbacks. It is also not valid to
2298 /// call if [State.mounted] returns false.
2299 ///
2300 /// If the render object is a [RenderBox], which is the common case, then the
2301 /// size of the render object can be obtained from the [size] getter. This is
2302 /// only valid after the layout phase, and should therefore only be examined
2303 /// from paint callbacks or interaction event handlers (e.g. gesture
2304 /// callbacks).
2305 ///
2306 /// For details on the different phases of a frame, see the discussion at
2307 /// [WidgetsBinding.drawFrame].
2308 ///
2309 /// Calling this method is theoretically relatively expensive (O(N) in the
2310 /// depth of the tree), but in practice is usually cheap because the tree
2311 /// usually has many render objects and therefore the distance to the nearest
2312 /// render object is usually short.
2313 RenderObject? findRenderObject();
2314
2315 /// The size of the [RenderBox] returned by [findRenderObject].
2316 ///
2317 /// This getter will only return a valid result after the layout phase is
2318 /// complete. It is therefore not valid to call this from a build method.
2319 /// It should only be called from paint callbacks or interaction event
2320 /// handlers (e.g. gesture callbacks).
2321 ///
2322 /// For details on the different phases of a frame, see the discussion at
2323 /// [WidgetsBinding.drawFrame].
2324 ///
2325 /// This getter will only return a valid result if [findRenderObject] actually
2326 /// returns a [RenderBox]. If [findRenderObject] returns a render object that
2327 /// is not a subtype of [RenderBox] (e.g., [RenderView]), this getter will
2328 /// throw an exception in debug mode and will return null in release mode.
2329 ///
2330 /// Calling this getter is theoretically relatively expensive (O(N) in the
2331 /// depth of the tree), but in practice is usually cheap because the tree
2332 /// usually has many render objects and therefore the distance to the nearest
2333 /// render object is usually short.
2334 Size? get size;
2335
2336 /// Registers this build context with [ancestor] such that when
2337 /// [ancestor]'s widget changes this build context is rebuilt.
2338 ///
2339 /// Returns `ancestor.widget`.
2340 ///
2341 /// This method is rarely called directly. Most applications should use
2342 /// [dependOnInheritedWidgetOfExactType], which calls this method after finding
2343 /// the appropriate [InheritedElement] ancestor.
2344 ///
2345 /// All of the qualifications about when [dependOnInheritedWidgetOfExactType] can
2346 /// be called apply to this method as well.
2347 InheritedWidget dependOnInheritedElement(InheritedElement ancestor, {Object? aspect});
2348
2349 /// Returns the nearest widget of the given type `T` and creates a dependency
2350 /// on it, or null if no appropriate widget is found.
2351 ///
2352 /// The widget found will be a concrete [InheritedWidget] subclass, and
2353 /// calling [dependOnInheritedWidgetOfExactType] registers this build context
2354 /// with the returned widget. When that widget changes (or a new widget of
2355 /// that type is introduced, or the widget goes away), this build context is
2356 /// rebuilt so that it can obtain new values from that widget.
2357 ///
2358 /// {@template flutter.widgets.BuildContext.dependOnInheritedWidgetOfExactType}
2359 /// This is typically called implicitly from `of()` static methods, e.g.
2360 /// [Theme.of].
2361 ///
2362 /// This method should not be called from widget constructors or from
2363 /// [State.initState] methods, because those methods would not get called
2364 /// again if the inherited value were to change. To ensure that the widget
2365 /// correctly updates itself when the inherited value changes, only call this
2366 /// (directly or indirectly) from build methods, layout and paint callbacks,
2367 /// or from [State.didChangeDependencies] (which is called immediately after
2368 /// [State.initState]).
2369 ///
2370 /// This method should not be called from [State.dispose] because the element
2371 /// tree is no longer stable at that time. To refer to an ancestor from that
2372 /// method, save a reference to the ancestor in [State.didChangeDependencies].
2373 /// It is safe to use this method from [State.deactivate], which is called
2374 /// whenever the widget is removed from the tree.
2375 ///
2376 /// It is also possible to call this method from interaction event handlers
2377 /// (e.g. gesture callbacks) or timers, to obtain a value once, as long as
2378 /// that value is not cached and/or reused later.
2379 ///
2380 /// Calling this method is O(1) with a small constant factor, but will lead to
2381 /// the widget being rebuilt more often.
2382 ///
2383 /// Once a widget registers a dependency on a particular type by calling this
2384 /// method, it will be rebuilt, and [State.didChangeDependencies] will be
2385 /// called, whenever changes occur relating to that widget until the next time
2386 /// the widget or one of its ancestors is moved (for example, because an
2387 /// ancestor is added or removed).
2388 ///
2389 /// The [aspect] parameter is only used when `T` is an
2390 /// [InheritedWidget] subclasses that supports partial updates, like
2391 /// [InheritedModel]. It specifies what "aspect" of the inherited
2392 /// widget this context depends on.
2393 /// {@endtemplate}
2394 T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect});
2395
2396 /// Returns the nearest widget of the given [InheritedWidget] subclass `T` or
2397 /// null if an appropriate ancestor is not found.
2398 ///
2399 /// This method does not introduce a dependency the way that the more typical
2400 /// [dependOnInheritedWidgetOfExactType] does, so this context will not be
2401 /// rebuilt if the [InheritedWidget] changes. This function is meant for those
2402 /// uncommon use cases where a dependency is undesirable.
2403 ///
2404 /// This method should not be called from [State.dispose] because the element
2405 /// tree is no longer stable at that time. To refer to an ancestor from that
2406 /// method, save a reference to the ancestor in [State.didChangeDependencies].
2407 /// It is safe to use this method from [State.deactivate], which is called
2408 /// whenever the widget is removed from the tree.
2409 ///
2410 /// It is also possible to call this method from interaction event handlers
2411 /// (e.g. gesture callbacks) or timers, to obtain a value once, as long as
2412 /// that value is not cached and/or reused later.
2413 ///
2414 /// Calling this method is O(1) with a small constant factor.
2415 T? getInheritedWidgetOfExactType<T extends InheritedWidget>();
2416
2417 /// Obtains the element corresponding to the nearest widget of the given type `T`,
2418 /// which must be the type of a concrete [InheritedWidget] subclass.
2419 ///
2420 /// Returns null if no such element is found.
2421 ///
2422 /// {@template flutter.widgets.BuildContext.getElementForInheritedWidgetOfExactType}
2423 /// Calling this method is O(1) with a small constant factor.
2424 ///
2425 /// This method does not establish a relationship with the target in the way
2426 /// that [dependOnInheritedWidgetOfExactType] does.
2427 ///
2428 /// This method should not be called from [State.dispose] because the element
2429 /// tree is no longer stable at that time. To refer to an ancestor from that
2430 /// method, save a reference to the ancestor by calling
2431 /// [dependOnInheritedWidgetOfExactType] in [State.didChangeDependencies]. It is
2432 /// safe to use this method from [State.deactivate], which is called whenever
2433 /// the widget is removed from the tree.
2434 /// {@endtemplate}
2435 InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
2436
2437 /// Returns the nearest ancestor widget of the given type `T`, which must be the
2438 /// type of a concrete [Widget] subclass.
2439 ///
2440 /// {@template flutter.widgets.BuildContext.findAncestorWidgetOfExactType}
2441 /// In general, [dependOnInheritedWidgetOfExactType] is more useful, since
2442 /// inherited widgets will trigger consumers to rebuild when they change. This
2443 /// method is appropriate when used in interaction event handlers (e.g.
2444 /// gesture callbacks) or for performing one-off tasks such as asserting that
2445 /// you have or don't have a widget of a specific type as an ancestor. The
2446 /// return value of a Widget's build method should not depend on the value
2447 /// returned by this method, because the build context will not rebuild if the
2448 /// return value of this method changes. This could lead to a situation where
2449 /// data used in the build method changes, but the widget is not rebuilt.
2450 ///
2451 /// Calling this method is relatively expensive (O(N) in the depth of the
2452 /// tree). Only call this method if the distance from this widget to the
2453 /// desired ancestor is known to be small and bounded.
2454 ///
2455 /// This method should not be called from [State.deactivate] or [State.dispose]
2456 /// because the widget tree is no longer stable at that time. To refer to
2457 /// an ancestor from one of those methods, save a reference to the ancestor
2458 /// by calling [findAncestorWidgetOfExactType] in [State.didChangeDependencies].
2459 ///
2460 /// Returns null if a widget of the requested type does not appear in the
2461 /// ancestors of this context.
2462 /// {@endtemplate}
2463 T? findAncestorWidgetOfExactType<T extends Widget>();
2464
2465 /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
2466 /// that is an instance of the given type `T`.
2467 ///
2468 /// {@template flutter.widgets.BuildContext.findAncestorStateOfType}
2469 /// This should not be used from build methods, because the build context will
2470 /// not be rebuilt if the value that would be returned by this method changes.
2471 /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2472 /// cases. This method is useful for changing the state of an ancestor widget in
2473 /// a one-off manner, for example, to cause an ancestor scrolling list to
2474 /// scroll this build context's widget into view, or to move the focus in
2475 /// response to user interaction.
2476 ///
2477 /// In general, though, consider using a callback that triggers a stateful
2478 /// change in the ancestor rather than using the imperative style implied by
2479 /// this method. This will usually lead to more maintainable and reusable code
2480 /// since it decouples widgets from each other.
2481 ///
2482 /// Calling this method is relatively expensive (O(N) in the depth of the
2483 /// tree). Only call this method if the distance from this widget to the
2484 /// desired ancestor is known to be small and bounded.
2485 ///
2486 /// This method should not be called from [State.deactivate] or [State.dispose]
2487 /// because the widget tree is no longer stable at that time. To refer to
2488 /// an ancestor from one of those methods, save a reference to the ancestor
2489 /// by calling [findAncestorStateOfType] in [State.didChangeDependencies].
2490 /// {@endtemplate}
2491 ///
2492 /// {@tool snippet}
2493 ///
2494 /// ```dart
2495 /// ScrollableState? scrollable = context.findAncestorStateOfType<ScrollableState>();
2496 /// ```
2497 /// {@end-tool}
2498 T? findAncestorStateOfType<T extends State>();
2499
2500 /// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
2501 /// that is an instance of the given type `T`.
2502 ///
2503 /// {@template flutter.widgets.BuildContext.findRootAncestorStateOfType}
2504 /// Functions the same way as [findAncestorStateOfType] but keeps visiting subsequent
2505 /// ancestors until there are none of the type instance of `T` remaining.
2506 /// Then returns the last one found.
2507 ///
2508 /// This operation is O(N) as well though N is the entire widget tree rather than
2509 /// a subtree.
2510 /// {@endtemplate}
2511 T? findRootAncestorStateOfType<T extends State>();
2512
2513 /// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
2514 /// that is an instance of the given type `T`.
2515 ///
2516 /// {@template flutter.widgets.BuildContext.findAncestorRenderObjectOfType}
2517 /// This should not be used from build methods, because the build context will
2518 /// not be rebuilt if the value that would be returned by this method changes.
2519 /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2520 /// cases. This method is useful only in esoteric cases where a widget needs
2521 /// to cause an ancestor to change its layout or paint behavior. For example,
2522 /// it is used by [Material] so that [InkWell] widgets can trigger the ink
2523 /// splash on the [Material]'s actual render object.
2524 ///
2525 /// Calling this method is relatively expensive (O(N) in the depth of the
2526 /// tree). Only call this method if the distance from this widget to the
2527 /// desired ancestor is known to be small and bounded.
2528 ///
2529 /// This method should not be called from [State.deactivate] or [State.dispose]
2530 /// because the widget tree is no longer stable at that time. To refer to
2531 /// an ancestor from one of those methods, save a reference to the ancestor
2532 /// by calling [findAncestorRenderObjectOfType] in [State.didChangeDependencies].
2533 /// {@endtemplate}
2534 T? findAncestorRenderObjectOfType<T extends RenderObject>();
2535
2536 /// Walks the ancestor chain, starting with the parent of this build context's
2537 /// widget, invoking the argument for each ancestor.
2538 ///
2539 /// {@template flutter.widgets.BuildContext.visitAncestorElements}
2540 /// The callback is given a reference to the ancestor widget's corresponding
2541 /// [Element] object. The walk stops when it reaches the root widget or when
2542 /// the callback returns false. The callback must not return null.
2543 ///
2544 /// This is useful for inspecting the widget tree.
2545 ///
2546 /// Calling this method is relatively expensive (O(N) in the depth of the tree).
2547 ///
2548 /// This method should not be called from [State.deactivate] or [State.dispose]
2549 /// because the element tree is no longer stable at that time. To refer to
2550 /// an ancestor from one of those methods, save a reference to the ancestor
2551 /// by calling [visitAncestorElements] in [State.didChangeDependencies].
2552 /// {@endtemplate}
2553 void visitAncestorElements(ConditionalElementVisitor visitor);
2554
2555 /// Walks the children of this widget.
2556 ///
2557 /// {@template flutter.widgets.BuildContext.visitChildElements}
2558 /// This is useful for applying changes to children after they are built
2559 /// without waiting for the next frame, especially if the children are known,
2560 /// and especially if there is exactly one child (as is always the case for
2561 /// [StatefulWidget]s or [StatelessWidget]s).
2562 ///
2563 /// Calling this method is very cheap for build contexts that correspond to
2564 /// [StatefulWidget]s or [StatelessWidget]s (O(1), since there's only one
2565 /// child).
2566 ///
2567 /// Calling this method is potentially expensive for build contexts that
2568 /// correspond to [RenderObjectWidget]s (O(N) in the number of children).
2569 ///
2570 /// Calling this method recursively is extremely expensive (O(N) in the number
2571 /// of descendants), and should be avoided if possible. Generally it is
2572 /// significantly cheaper to use an [InheritedWidget] and have the descendants
2573 /// pull data down, than it is to use [visitChildElements] recursively to push
2574 /// data down to them.
2575 /// {@endtemplate}
2576 void visitChildElements(ElementVisitor visitor);
2577
2578 /// Start bubbling this notification at the given build context.
2579 ///
2580 /// The notification will be delivered to any [NotificationListener] widgets
2581 /// with the appropriate type parameters that are ancestors of the given
2582 /// [BuildContext].
2583 void dispatchNotification(Notification notification);
2584
2585 /// Returns a description of the [Element] associated with the current build context.
2586 ///
2587 /// The `name` is typically something like "The element being rebuilt was".
2588 ///
2589 /// See also:
2590 ///
2591 /// * [Element.describeElements], which can be used to describe a list of elements.
2592 DiagnosticsNode describeElement(
2593 String name, {
2594 DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
2595 });
2596
2597 /// Returns a description of the [Widget] associated with the current build context.
2598 ///
2599 /// The `name` is typically something like "The widget being rebuilt was".
2600 DiagnosticsNode describeWidget(
2601 String name, {
2602 DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
2603 });
2604
2605 /// Adds a description of a specific type of widget missing from the current
2606 /// build context's ancestry tree.
2607 ///
2608 /// You can find an example of using this method in [debugCheckHasMaterial].
2609 List<DiagnosticsNode> describeMissingAncestor({required Type expectedAncestorType});
2610
2611 /// Adds a description of the ownership chain from a specific [Element]
2612 /// to the error report.
2613 ///
2614 /// The ownership chain is useful for debugging the source of an element.
2615 DiagnosticsNode describeOwnershipChain(String name);
2616}
2617
2618/// A class that determines the scope of a [BuildOwner.buildScope] operation.
2619///
2620/// The [BuildOwner.buildScope] method rebuilds all dirty [Element]s who share
2621/// the same [Element.buildScope] as its `context` argument, and skips those
2622/// with a different [Element.buildScope].
2623///
2624/// [Element]s by default have the same `buildScope` as their parents. Special
2625/// [Element]s may override [Element.buildScope] to create an isolated build scope
2626/// for its descendants. The [LayoutBuilder] widget, for example, establishes its
2627/// own [BuildScope] such that no descendant [Element]s may rebuild prematurely
2628/// until the incoming constraints are known.
2629final class BuildScope {
2630 /// Creates a [BuildScope] with an optional [scheduleRebuild] callback.
2631 BuildScope({this.scheduleRebuild});
2632
2633 // Whether `scheduleRebuild` is called.
2634 bool _buildScheduled = false;
2635 // Whether [BuildOwner.buildScope] is actively running in this [BuildScope].
2636 bool _building = false;
2637
2638 /// An optional [VoidCallback] that will be called when [Element]s in this
2639 /// [BuildScope] are marked as dirty for the first time.
2640 ///
2641 /// This callback usually signifies that the [BuildOwner.buildScope] method
2642 /// must be called at a later time in this frame to rebuild dirty elements in
2643 /// this [BuildScope]. It will **not** be called if this scope is actively being
2644 /// built by [BuildOwner.buildScope], since the [BuildScope] will be clean when
2645 /// [BuildOwner.buildScope] returns.
2646 final VoidCallback? scheduleRebuild;
2647
2648 /// Whether [_dirtyElements] need to be sorted again as a result of more
2649 /// elements becoming dirty during the build.
2650 ///
2651 /// This is necessary to preserve the sort order defined by [Element._sort].
2652 ///
2653 /// This field is set to null when [BuildOwner.buildScope] is not actively
2654 /// rebuilding the widget tree.
2655 bool? _dirtyElementsNeedsResorting;
2656 final List<Element> _dirtyElements = <Element>[];
2657
2658 @pragma('dart2js:tryInline')
2659 @pragma('vm:prefer-inline')
2660 @pragma('wasm:prefer-inline')
2661 void _scheduleBuildFor(Element element) {
2662 assert(identical(element.buildScope, this));
2663 if (!element._inDirtyList) {
2664 _dirtyElements.add(element);
2665 element._inDirtyList = true;
2666 }
2667 if (!_buildScheduled && !_building) {
2668 _buildScheduled = true;
2669 scheduleRebuild?.call();
2670 }
2671 if (_dirtyElementsNeedsResorting != null) {
2672 _dirtyElementsNeedsResorting = true;
2673 }
2674 }
2675
2676 @pragma('dart2js:tryInline')
2677 @pragma('vm:prefer-inline')
2678 @pragma('wasm:prefer-inline')
2679 @pragma('vm:notify-debugger-on-exception')
2680 void _tryRebuild(Element element) {
2681 assert(element._inDirtyList);
2682 assert(identical(element.buildScope, this));
2683 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(element.widget);
2684 if (isTimelineTracked) {
2685 Map<String, String>? debugTimelineArguments;
2686 assert(() {
2687 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
2688 debugTimelineArguments = element.widget.toDiagnosticsNode().toTimelineArguments();
2689 }
2690 return true;
2691 }());
2692 FlutterTimeline.startSync('${element.widget.runtimeType}', arguments: debugTimelineArguments);
2693 }
2694 try {
2695 element.rebuild();
2696 } catch (e, stack) {
2697 _reportException(
2698 ErrorDescription('while rebuilding dirty elements'),
2699 e,
2700 stack,
2701 informationCollector: () => <DiagnosticsNode>[
2702 if (kDebugMode) DiagnosticsDebugCreator(DebugCreator(element)),
2703 element.describeElement('The element being rebuilt at the time was'),
2704 ],
2705 );
2706 }
2707 if (isTimelineTracked) {
2708 FlutterTimeline.finishSync();
2709 }
2710 }
2711
2712 bool _debugAssertElementInScope(Element element, Element debugBuildRoot) {
2713 final bool isInScope = element._debugIsDescendantOf(debugBuildRoot) || !element.debugIsActive;
2714 if (isInScope) {
2715 return true;
2716 }
2717 throw FlutterError.fromParts(<DiagnosticsNode>[
2718 ErrorSummary('Tried to build dirty widget in the wrong build scope.'),
2719 ErrorDescription(
2720 'A widget which was marked as dirty and is still active was scheduled to be built, '
2721 'but the current build scope unexpectedly does not contain that widget.',
2722 ),
2723 ErrorHint(
2724 'Sometimes this is detected when an element is removed from the widget tree, but the '
2725 'element somehow did not get marked as inactive. In that case, it might be caused by '
2726 'an ancestor element failing to implement visitChildren correctly, thus preventing '
2727 'some or all of its descendants from being correctly deactivated.',
2728 ),
2729 DiagnosticsProperty<Element>(
2730 'The root of the build scope was',
2731 debugBuildRoot,
2732 style: DiagnosticsTreeStyle.errorProperty,
2733 ),
2734 DiagnosticsProperty<Element>(
2735 'The offending element (which does not appear to be a descendant of the root of the build scope) was',
2736 element,
2737 style: DiagnosticsTreeStyle.errorProperty,
2738 ),
2739 ]);
2740 }
2741
2742 @pragma('vm:notify-debugger-on-exception')
2743 void _flushDirtyElements({required Element debugBuildRoot}) {
2744 assert(_dirtyElementsNeedsResorting == null, '_flushDirtyElements must be non-reentrant');
2745 _dirtyElements.sort(Element._sort);
2746 _dirtyElementsNeedsResorting = false;
2747 try {
2748 for (int index = 0; index < _dirtyElements.length; index = _dirtyElementIndexAfter(index)) {
2749 final Element element = _dirtyElements[index];
2750 if (identical(element.buildScope, this)) {
2751 assert(_debugAssertElementInScope(element, debugBuildRoot));
2752 _tryRebuild(element);
2753 }
2754 }
2755 assert(() {
2756 final Iterable<Element> missedElements = _dirtyElements.where(
2757 (Element element) =>
2758 element.debugIsActive && element.dirty && identical(element.buildScope, this),
2759 );
2760 if (missedElements.isNotEmpty) {
2761 throw FlutterError.fromParts(<DiagnosticsNode>[
2762 ErrorSummary('buildScope missed some dirty elements.'),
2763 ErrorHint(
2764 'This probably indicates that the dirty list should have been resorted but was not.',
2765 ),
2766 DiagnosticsProperty<Element>(
2767 'The context argument of the buildScope call was',
2768 debugBuildRoot,
2769 style: DiagnosticsTreeStyle.errorProperty,
2770 ),
2771 Element.describeElements(
2772 'The list of missed elements at the end of the buildScope call was',
2773 missedElements,
2774 ),
2775 ]);
2776 }
2777 return true;
2778 }());
2779 } finally {
2780 for (final Element element in _dirtyElements) {
2781 if (identical(element.buildScope, this)) {
2782 element._inDirtyList = false;
2783 }
2784 }
2785 _dirtyElements.clear();
2786 _dirtyElementsNeedsResorting = null;
2787 _buildScheduled = false;
2788 }
2789 }
2790
2791 @pragma('dart2js:tryInline')
2792 @pragma('vm:prefer-inline')
2793 @pragma('wasm:prefer-inline')
2794 int _dirtyElementIndexAfter(int index) {
2795 if (!_dirtyElementsNeedsResorting!) {
2796 return index + 1;
2797 }
2798 index += 1;
2799 _dirtyElements.sort(Element._sort);
2800 _dirtyElementsNeedsResorting = false;
2801 while (index > 0 && _dirtyElements[index - 1].dirty) {
2802 // It is possible for previously dirty but inactive widgets to move right in the list.
2803 // We therefore have to move the index left in the list to account for this.
2804 // We don't know how many could have moved. However, we do know that the only possible
2805 // change to the list is that nodes that were previously to the left of the index have
2806 // now moved to be to the right of the right-most cleaned node, and we do know that
2807 // all the clean nodes were to the left of the index. So we move the index left
2808 // until just after the right-most clean node.
2809 index -= 1;
2810 }
2811 assert(() {
2812 for (int i = index - 1; i >= 0; i -= 1) {
2813 final Element element = _dirtyElements[i];
2814 assert(!element.dirty || element._lifecycleState != _ElementLifecycle.active);
2815 }
2816 return true;
2817 }());
2818 return index;
2819 }
2820}
2821
2822/// Manager class for the widgets framework.
2823///
2824/// This class tracks which widgets need rebuilding, and handles other tasks
2825/// that apply to widget trees as a whole, such as managing the inactive element
2826/// list for the tree and triggering the "reassemble" command when necessary
2827/// during hot reload when debugging.
2828///
2829/// The main build owner is typically owned by the [WidgetsBinding], and is
2830/// driven from the operating system along with the rest of the
2831/// build/layout/paint pipeline.
2832///
2833/// Additional build owners can be built to manage off-screen widget trees.
2834///
2835/// To assign a build owner to a tree, use the
2836/// [RootElementMixin.assignOwner] method on the root element of the
2837/// widget tree.
2838///
2839/// {@tool dartpad}
2840/// This example shows how to build an off-screen widget tree used to measure
2841/// the layout size of the rendered tree. For some use cases, the simpler
2842/// [Offstage] widget may be a better alternative to this approach.
2843///
2844/// ** See code in examples/api/lib/widgets/framework/build_owner.0.dart **
2845/// {@end-tool}
2846class BuildOwner {
2847 /// Creates an object that manages widgets.
2848 ///
2849 /// If the `focusManager` argument is not specified or is null, this will
2850 /// construct a new [FocusManager] and register its global input handlers
2851 /// via [FocusManager.registerGlobalHandlers], which will modify static
2852 /// state. Callers wishing to avoid altering this state can explicitly pass
2853 /// a focus manager here.
2854 BuildOwner({this.onBuildScheduled, FocusManager? focusManager})
2855 : focusManager = focusManager ?? (FocusManager()..registerGlobalHandlers());
2856
2857 /// Called on each build pass when the first buildable element is marked
2858 /// dirty.
2859 VoidCallback? onBuildScheduled;
2860
2861 final _InactiveElements _inactiveElements = _InactiveElements();
2862
2863 bool _scheduledFlushDirtyElements = false;
2864
2865 /// The object in charge of the focus tree.
2866 ///
2867 /// Rarely used directly. Instead, consider using [FocusScope.of] to obtain
2868 /// the [FocusScopeNode] for a given [BuildContext].
2869 ///
2870 /// See [FocusManager] for more details.
2871 ///
2872 /// This field will default to a [FocusManager] that has registered its
2873 /// global input handlers via [FocusManager.registerGlobalHandlers]. Callers
2874 /// wishing to avoid registering those handlers (and modifying the associated
2875 /// static state) can explicitly pass a focus manager to the [BuildOwner.new]
2876 /// constructor.
2877 FocusManager focusManager;
2878
2879 /// Adds an element to the dirty elements list so that it will be rebuilt
2880 /// when [WidgetsBinding.drawFrame] calls [buildScope].
2881 void scheduleBuildFor(Element element) {
2882 assert(element.owner == this);
2883 assert(element._parentBuildScope != null);
2884 assert(() {
2885 if (debugPrintScheduleBuildForStacks) {
2886 debugPrintStack(
2887 label:
2888 'scheduleBuildFor() called for $element${element.buildScope._dirtyElements.contains(element) ? " (ALREADY IN LIST)" : ""}',
2889 );
2890 }
2891 if (!element.dirty) {
2892 throw FlutterError.fromParts(<DiagnosticsNode>[
2893 ErrorSummary('scheduleBuildFor() called for a widget that is not marked as dirty.'),
2894 element.describeElement('The method was called for the following element'),
2895 ErrorDescription(
2896 'This element is not current marked as dirty. Make sure to set the dirty flag before '
2897 'calling scheduleBuildFor().',
2898 ),
2899 ErrorHint(
2900 'If you did not attempt to call scheduleBuildFor() yourself, then this probably '
2901 'indicates a bug in the widgets framework. Please report it:\n'
2902 ' https://github.com/flutter/flutter/issues/new?template=02_bug.yml',
2903 ),
2904 ]);
2905 }
2906 return true;
2907 }());
2908 final BuildScope buildScope = element.buildScope;
2909 assert(() {
2910 if (debugPrintScheduleBuildForStacks && element._inDirtyList) {
2911 debugPrintStack(
2912 label:
2913 'BuildOwner.scheduleBuildFor() called; '
2914 '_dirtyElementsNeedsResorting was ${buildScope._dirtyElementsNeedsResorting} (now true); '
2915 'The dirty list for the current build scope is: ${buildScope._dirtyElements}',
2916 );
2917 }
2918 if (!_debugBuilding && element._inDirtyList) {
2919 throw FlutterError.fromParts(<DiagnosticsNode>[
2920 ErrorSummary('BuildOwner.scheduleBuildFor() called inappropriately.'),
2921 ErrorHint(
2922 'The BuildOwner.scheduleBuildFor() method called on an Element '
2923 'that is already in the dirty list.',
2924 ),
2925 element.describeElement('the dirty Element was'),
2926 ]);
2927 }
2928 return true;
2929 }());
2930 if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
2931 _scheduledFlushDirtyElements = true;
2932 onBuildScheduled!();
2933 }
2934 buildScope._scheduleBuildFor(element);
2935 assert(() {
2936 if (debugPrintScheduleBuildForStacks) {
2937 debugPrint("...the build scope's dirty list is now: $buildScope._dirtyElements");
2938 }
2939 return true;
2940 }());
2941 }
2942
2943 int _debugStateLockLevel = 0;
2944 bool get _debugStateLocked => _debugStateLockLevel > 0;
2945
2946 /// Whether this widget tree is in the build phase.
2947 ///
2948 /// Only valid when asserts are enabled.
2949 bool get debugBuilding => _debugBuilding;
2950 bool _debugBuilding = false;
2951 Element? _debugCurrentBuildTarget;
2952
2953 /// Establishes a scope in which calls to [State.setState] are forbidden, and
2954 /// calls the given `callback`.
2955 ///
2956 /// This mechanism is used to ensure that, for instance, [State.dispose] does
2957 /// not call [State.setState].
2958 void lockState(VoidCallback callback) {
2959 assert(_debugStateLockLevel >= 0);
2960 assert(() {
2961 _debugStateLockLevel += 1;
2962 return true;
2963 }());
2964 try {
2965 callback();
2966 } finally {
2967 assert(() {
2968 _debugStateLockLevel -= 1;
2969 return true;
2970 }());
2971 }
2972 assert(_debugStateLockLevel >= 0);
2973 }
2974
2975 /// Establishes a scope for updating the widget tree, and calls the given
2976 /// `callback`, if any. Then, builds all the elements that were marked as
2977 /// dirty using [scheduleBuildFor], in depth order.
2978 ///
2979 /// This mechanism prevents build methods from transitively requiring other
2980 /// build methods to run, potentially causing infinite loops.
2981 ///
2982 /// The dirty list is processed after `callback` returns, building all the
2983 /// elements that were marked as dirty using [scheduleBuildFor], in depth
2984 /// order. If elements are marked as dirty while this method is running, they
2985 /// must be deeper than the `context` node, and deeper than any
2986 /// previously-built node in this pass.
2987 ///
2988 /// To flush the current dirty list without performing any other work, this
2989 /// function can be called with no callback. This is what the framework does
2990 /// each frame, in [WidgetsBinding.drawFrame].
2991 ///
2992 /// Only one [buildScope] can be active at a time.
2993 ///
2994 /// A [buildScope] implies a [lockState] scope as well.
2995 ///
2996 /// To print a console message every time this method is called, set
2997 /// [debugPrintBuildScope] to true. This is useful when debugging problems
2998 /// involving widgets not getting marked dirty, or getting marked dirty too
2999 /// often.
3000 @pragma('vm:notify-debugger-on-exception')
3001 void buildScope(Element context, [VoidCallback? callback]) {
3002 final BuildScope buildScope = context.buildScope;
3003 if (callback == null && buildScope._dirtyElements.isEmpty) {
3004 return;
3005 }
3006 assert(_debugStateLockLevel >= 0);
3007 assert(!_debugBuilding);
3008 assert(() {
3009 if (debugPrintBuildScope) {
3010 debugPrint(
3011 'buildScope called with context $context; '
3012 "its build scope's dirty list is: ${buildScope._dirtyElements}",
3013 );
3014 }
3015 _debugStateLockLevel += 1;
3016 _debugBuilding = true;
3017 return true;
3018 }());
3019 if (!kReleaseMode) {
3020 Map<String, String>? debugTimelineArguments;
3021 assert(() {
3022 if (debugEnhanceBuildTimelineArguments) {
3023 debugTimelineArguments = <String, String>{
3024 'build scope dirty count': '${buildScope._dirtyElements.length}',
3025 'build scope dirty list': '${buildScope._dirtyElements}',
3026 'lock level': '$_debugStateLockLevel',
3027 'scope context': '$context',
3028 };
3029 }
3030 return true;
3031 }());
3032 FlutterTimeline.startSync('BUILD', arguments: debugTimelineArguments);
3033 }
3034 try {
3035 _scheduledFlushDirtyElements = true;
3036 buildScope._building = true;
3037 if (callback != null) {
3038 assert(_debugStateLocked);
3039 Element? debugPreviousBuildTarget;
3040 assert(() {
3041 debugPreviousBuildTarget = _debugCurrentBuildTarget;
3042 _debugCurrentBuildTarget = context;
3043 return true;
3044 }());
3045 try {
3046 callback();
3047 } finally {
3048 assert(() {
3049 assert(_debugCurrentBuildTarget == context);
3050 _debugCurrentBuildTarget = debugPreviousBuildTarget;
3051 _debugElementWasRebuilt(context);
3052 return true;
3053 }());
3054 }
3055 }
3056 buildScope._flushDirtyElements(debugBuildRoot: context);
3057 } finally {
3058 buildScope._building = false;
3059 _scheduledFlushDirtyElements = false;
3060 if (!kReleaseMode) {
3061 FlutterTimeline.finishSync();
3062 }
3063 assert(_debugBuilding);
3064 assert(() {
3065 _debugBuilding = false;
3066 _debugStateLockLevel -= 1;
3067 if (debugPrintBuildScope) {
3068 debugPrint('buildScope finished');
3069 }
3070 return true;
3071 }());
3072 }
3073 assert(_debugStateLockLevel >= 0);
3074 }
3075
3076 Map<Element, Set<GlobalKey>>? _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans;
3077
3078 void _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(
3079 Element node,
3080 GlobalKey key,
3081 ) {
3082 final Map<Element, Set<GlobalKey>> map =
3083 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans ??=
3084 HashMap<Element, Set<GlobalKey>>();
3085 final Set<GlobalKey> keys = map.putIfAbsent(node, () => HashSet<GlobalKey>());
3086 keys.add(key);
3087 }
3088
3089 void _debugElementWasRebuilt(Element node) {
3090 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.remove(node);
3091 }
3092
3093 final Map<GlobalKey, Element> _globalKeyRegistry = <GlobalKey, Element>{};
3094
3095 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
3096 // eliminate unused fields, but not their initializers.
3097 @_debugOnly
3098 final Set<Element>? _debugIllFatedElements = kDebugMode ? HashSet<Element>() : null;
3099
3100 // This map keeps track which child reserves the global key with the parent.
3101 // Parent, child -> global key.
3102 // This provides us a way to remove old reservation while parent rebuilds the
3103 // child in the same slot.
3104 //
3105 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
3106 // eliminate unused fields, but not their initializers.
3107 @_debugOnly
3108 final Map<Element, Map<Element, GlobalKey>>? _debugGlobalKeyReservations = kDebugMode
3109 ? <Element, Map<Element, GlobalKey>>{}
3110 : null;
3111
3112 /// The number of [GlobalKey] instances that are currently associated with
3113 /// [Element]s that have been built by this build owner.
3114 int get globalKeyCount => _globalKeyRegistry.length;
3115
3116 void _debugRemoveGlobalKeyReservationFor(Element parent, Element child) {
3117 assert(() {
3118 _debugGlobalKeyReservations?[parent]?.remove(child);
3119 return true;
3120 }());
3121 }
3122
3123 void _registerGlobalKey(GlobalKey key, Element element) {
3124 assert(() {
3125 if (_globalKeyRegistry.containsKey(key)) {
3126 final Element oldElement = _globalKeyRegistry[key]!;
3127 assert(element.widget.runtimeType != oldElement.widget.runtimeType);
3128 _debugIllFatedElements?.add(oldElement);
3129 }
3130 return true;
3131 }());
3132 _globalKeyRegistry[key] = element;
3133 }
3134
3135 void _unregisterGlobalKey(GlobalKey key, Element element) {
3136 assert(() {
3137 if (_globalKeyRegistry.containsKey(key) && _globalKeyRegistry[key] != element) {
3138 final Element oldElement = _globalKeyRegistry[key]!;
3139 assert(element.widget.runtimeType != oldElement.widget.runtimeType);
3140 }
3141 return true;
3142 }());
3143 if (_globalKeyRegistry[key] == element) {
3144 _globalKeyRegistry.remove(key);
3145 }
3146 }
3147
3148 void _debugReserveGlobalKeyFor(Element parent, Element child, GlobalKey key) {
3149 assert(() {
3150 _debugGlobalKeyReservations?[parent] ??= <Element, GlobalKey>{};
3151 _debugGlobalKeyReservations?[parent]![child] = key;
3152 return true;
3153 }());
3154 }
3155
3156 void _debugVerifyGlobalKeyReservation() {
3157 assert(() {
3158 final Map<GlobalKey, Element> keyToParent = <GlobalKey, Element>{};
3159 _debugGlobalKeyReservations?.forEach((Element parent, Map<Element, GlobalKey> childToKey) {
3160 // We ignore parent that are unmounted or detached.
3161 if (parent._lifecycleState == _ElementLifecycle.defunct ||
3162 parent.renderObject?.attached == false) {
3163 return;
3164 }
3165 childToKey.forEach((Element child, GlobalKey key) {
3166 // If parent = null, the node is deactivated by its parent and is
3167 // not re-attached to other part of the tree. We should ignore this
3168 // node.
3169 if (child._parent == null) {
3170 return;
3171 }
3172 // It is possible the same key registers to the same parent twice
3173 // with different children. That is illegal, but it is not in the
3174 // scope of this check. Such error will be detected in
3175 // _debugVerifyIllFatedPopulation or
3176 // _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.
3177 if (keyToParent.containsKey(key) && keyToParent[key] != parent) {
3178 // We have duplication reservations for the same global key.
3179 final Element older = keyToParent[key]!;
3180 final Element newer = parent;
3181 final FlutterError error;
3182 if (older.toString() != newer.toString()) {
3183 error = FlutterError.fromParts(<DiagnosticsNode>[
3184 ErrorSummary('Multiple widgets used the same GlobalKey.'),
3185 ErrorDescription(
3186 'The key $key was used by multiple widgets. The parents of those widgets were:\n'
3187 '- $older\n'
3188 '- $newer\n'
3189 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
3190 ),
3191 ]);
3192 } else {
3193 error = FlutterError.fromParts(<DiagnosticsNode>[
3194 ErrorSummary('Multiple widgets used the same GlobalKey.'),
3195 ErrorDescription(
3196 'The key $key was used by multiple widgets. The parents of those widgets were '
3197 'different widgets that both had the following description:\n'
3198 ' $parent\n'
3199 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
3200 ),
3201 ]);
3202 }
3203 // Fix the tree by removing the duplicated child from one of its
3204 // parents to resolve the duplicated key issue. This allows us to
3205 // tear down the tree during testing without producing additional
3206 // misleading exceptions.
3207 if (child._parent != older) {
3208 older.visitChildren((Element currentChild) {
3209 if (currentChild == child) {
3210 older.forgetChild(child);
3211 }
3212 });
3213 }
3214 if (child._parent != newer) {
3215 newer.visitChildren((Element currentChild) {
3216 if (currentChild == child) {
3217 newer.forgetChild(child);
3218 }
3219 });
3220 }
3221 throw error;
3222 } else {
3223 keyToParent[key] = parent;
3224 }
3225 });
3226 });
3227 _debugGlobalKeyReservations?.clear();
3228 return true;
3229 }());
3230 }
3231
3232 void _debugVerifyIllFatedPopulation() {
3233 assert(() {
3234 Map<GlobalKey, Set<Element>>? duplicates;
3235 for (final Element element in _debugIllFatedElements ?? const <Element>{}) {
3236 if (element._lifecycleState != _ElementLifecycle.defunct) {
3237 assert(element.widget.key != null);
3238 final GlobalKey key = element.widget.key! as GlobalKey;
3239 assert(_globalKeyRegistry.containsKey(key));
3240 duplicates ??= <GlobalKey, Set<Element>>{};
3241 // Uses ordered set to produce consistent error message.
3242 final Set<Element> elements = duplicates.putIfAbsent(key, () => <Element>{});
3243 elements.add(element);
3244 elements.add(_globalKeyRegistry[key]!);
3245 }
3246 }
3247 _debugIllFatedElements?.clear();
3248 if (duplicates != null) {
3249 final List<DiagnosticsNode> information = <DiagnosticsNode>[];
3250 information.add(ErrorSummary('Multiple widgets used the same GlobalKey.'));
3251 for (final GlobalKey key in duplicates.keys) {
3252 final Set<Element> elements = duplicates[key]!;
3253 // TODO(jacobr): this will omit the '- ' before each widget name and
3254 // use the more standard whitespace style instead. Please let me know
3255 // if the '- ' style is a feature we want to maintain and we can add
3256 // another tree style that supports it. I also see '* ' in some places
3257 // so it would be nice to unify and normalize.
3258 information.add(
3259 Element.describeElements(
3260 'The key $key was used by ${elements.length} widgets',
3261 elements,
3262 ),
3263 );
3264 }
3265 information.add(
3266 ErrorDescription(
3267 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
3268 ),
3269 );
3270 throw FlutterError.fromParts(information);
3271 }
3272 return true;
3273 }());
3274 }
3275
3276 /// Complete the element build pass by unmounting any elements that are no
3277 /// longer active.
3278 ///
3279 /// This is called by [WidgetsBinding.drawFrame].
3280 ///
3281 /// In debug mode, this also runs some sanity checks, for example checking for
3282 /// duplicate global keys.
3283 @pragma('vm:notify-debugger-on-exception')
3284 void finalizeTree() {
3285 if (!kReleaseMode) {
3286 FlutterTimeline.startSync('FINALIZE TREE');
3287 }
3288 try {
3289 lockState(_inactiveElements._unmountAll); // this unregisters the GlobalKeys
3290 assert(() {
3291 try {
3292 _debugVerifyGlobalKeyReservation();
3293 _debugVerifyIllFatedPopulation();
3294 if (_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.isNotEmpty ?? false) {
3295 final Set<GlobalKey> keys = HashSet<GlobalKey>();
3296 for (final Element element
3297 in _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.keys) {
3298 if (element._lifecycleState != _ElementLifecycle.defunct) {
3299 keys.addAll(
3300 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans![element]!,
3301 );
3302 }
3303 }
3304 if (keys.isNotEmpty) {
3305 final Map<String, int> keyStringCount = HashMap<String, int>();
3306 for (final String key in keys.map<String>((GlobalKey key) => key.toString())) {
3307 if (keyStringCount.containsKey(key)) {
3308 keyStringCount.update(key, (int value) => value + 1);
3309 } else {
3310 keyStringCount[key] = 1;
3311 }
3312 }
3313 final List<String> keyLabels = <String>[
3314 for (final MapEntry<String, int>(:String key, value: int count)
3315 in keyStringCount.entries)
3316 if (count == 1)
3317 key
3318 else
3319 '$key ($count different affected keys had this toString representation)',
3320 ];
3321 final Iterable<Element> elements =
3322 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.keys;
3323 final Map<String, int> elementStringCount = HashMap<String, int>();
3324 for (final String element in elements.map<String>(
3325 (Element element) => element.toString(),
3326 )) {
3327 if (elementStringCount.containsKey(element)) {
3328 elementStringCount.update(element, (int value) => value + 1);
3329 } else {
3330 elementStringCount[element] = 1;
3331 }
3332 }
3333 final List<String> elementLabels = <String>[
3334 for (final MapEntry<String, int>(key: String element, value: int count)
3335 in elementStringCount.entries)
3336 if (count == 1)
3337 element
3338 else
3339 '$element ($count different affected elements had this toString representation)',
3340 ];
3341 assert(keyLabels.isNotEmpty);
3342 final String the = keys.length == 1 ? ' the' : '';
3343 final String s = keys.length == 1 ? '' : 's';
3344 final String were = keys.length == 1 ? 'was' : 'were';
3345 final String their = keys.length == 1 ? 'its' : 'their';
3346 final String respective = elementLabels.length == 1 ? '' : ' respective';
3347 final String those = keys.length == 1 ? 'that' : 'those';
3348 final String s2 = elementLabels.length == 1 ? '' : 's';
3349 final String those2 = elementLabels.length == 1 ? 'that' : 'those';
3350 final String they = elementLabels.length == 1 ? 'it' : 'they';
3351 final String think = elementLabels.length == 1 ? 'thinks' : 'think';
3352 final String are = elementLabels.length == 1 ? 'is' : 'are';
3353 // TODO(jacobr): make this error more structured to better expose which widgets had problems.
3354 throw FlutterError.fromParts(<DiagnosticsNode>[
3355 ErrorSummary('Duplicate GlobalKey$s detected in widget tree.'),
3356 // TODO(jacobr): refactor this code so the elements are clickable
3357 // in GUI debug tools.
3358 ErrorDescription(
3359 'The following GlobalKey$s $were specified multiple times in the widget tree. This will lead to '
3360 'parts of the widget tree being truncated unexpectedly, because the second time a key is seen, '
3361 'the previous instance is moved to the new location. The key$s $were:\n'
3362 '- ${keyLabels.join("\n ")}\n'
3363 'This was determined by noticing that after$the widget$s with the above global key$s $were moved '
3364 'out of $their$respective previous parent$s2, $those2 previous parent$s2 never updated during this frame, meaning '
3365 'that $they either did not update at all or updated before the widget$s $were moved, in either case '
3366 'implying that $they still $think that $they should have a child with $those global key$s.\n'
3367 'The specific parent$s2 that did not update after having one or more children forcibly removed '
3368 'due to GlobalKey reparenting $are:\n'
3369 '- ${elementLabels.join("\n ")}'
3370 '\nA GlobalKey can only be specified on one widget at a time in the widget tree.',
3371 ),
3372 ]);
3373 }
3374 }
3375 } finally {
3376 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.clear();
3377 }
3378 return true;
3379 }());
3380 } catch (e, stack) {
3381 // Catching the exception directly to avoid activating the ErrorWidget.
3382 // Since the tree is in a broken state, adding the ErrorWidget would
3383 // cause more exceptions.
3384 _reportException(ErrorSummary('while finalizing the widget tree'), e, stack);
3385 } finally {
3386 if (!kReleaseMode) {
3387 FlutterTimeline.finishSync();
3388 }
3389 }
3390 }
3391
3392 /// Cause the entire subtree rooted at the given [Element] to be entirely
3393 /// rebuilt. This is used by development tools when the application code has
3394 /// changed and is being hot-reloaded, to cause the widget tree to pick up any
3395 /// changed implementations.
3396 ///
3397 /// This is expensive and should not be called except during development.
3398 void reassemble(Element root) {
3399 if (!kReleaseMode) {
3400 FlutterTimeline.startSync('Preparing Hot Reload (widgets)');
3401 }
3402 try {
3403 assert(root._parent == null);
3404 assert(root.owner == this);
3405 root.reassemble();
3406 } finally {
3407 if (!kReleaseMode) {
3408 FlutterTimeline.finishSync();
3409 }
3410 }
3411 }
3412}
3413
3414/// Mixin this class to allow receiving [Notification] objects dispatched by
3415/// child elements.
3416///
3417/// See also:
3418/// * [NotificationListener], for a widget that allows consuming notifications.
3419mixin NotifiableElementMixin on Element {
3420 /// Called when a notification of the appropriate type arrives at this
3421 /// location in the tree.
3422 ///
3423 /// Return true to cancel the notification bubbling. Return false to
3424 /// allow the notification to continue to be dispatched to further ancestors.
3425 bool onNotification(Notification notification);
3426
3427 @override
3428 void attachNotificationTree() {
3429 _notificationTree = _NotificationNode(_parent?._notificationTree, this);
3430 }
3431}
3432
3433class _NotificationNode {
3434 _NotificationNode(this.parent, this.current);
3435
3436 NotifiableElementMixin? current;
3437 _NotificationNode? parent;
3438
3439 void dispatchNotification(Notification notification) {
3440 if (current?.onNotification(notification) ?? true) {
3441 return;
3442 }
3443 parent?.dispatchNotification(notification);
3444 }
3445}
3446
3447bool _isProfileBuildsEnabledFor(Widget widget) {
3448 return debugProfileBuildsEnabled ||
3449 (debugProfileBuildsEnabledUserWidgets && debugIsWidgetLocalCreation(widget));
3450}
3451
3452/// An instantiation of a [Widget] at a particular location in the tree.
3453///
3454/// Widgets describe how to configure a subtree but the same widget can be used
3455/// to configure multiple subtrees simultaneously because widgets are immutable.
3456/// An [Element] represents the use of a widget to configure a specific location
3457/// in the tree. Over time, the widget associated with a given element can
3458/// change, for example, if the parent widget rebuilds and creates a new widget
3459/// for this location.
3460///
3461/// Elements form a tree. Most elements have a unique child, but some widgets
3462/// (e.g., subclasses of [RenderObjectElement]) can have multiple children.
3463///
3464/// Elements have the following lifecycle:
3465///
3466/// * The framework creates an element by calling [Widget.createElement] on the
3467/// widget that will be used as the element's initial configuration.
3468/// * The framework calls [mount] to add the newly created element to the tree
3469/// at a given slot in a given parent. The [mount] method is responsible for
3470/// inflating any child widgets and calling [attachRenderObject] as
3471/// necessary to attach any associated render objects to the render tree.
3472/// * At this point, the element is considered "active" and might appear on
3473/// screen.
3474/// * At some point, the parent might decide to change the widget used to
3475/// configure this element, for example because the parent rebuilt with new
3476/// state. When this happens, the framework will call [update] with the new
3477/// widget. The new widget will always have the same [runtimeType] and key as
3478/// old widget. If the parent wishes to change the [runtimeType] or key of
3479/// the widget at this location in the tree, it can do so by unmounting this
3480/// element and inflating the new widget at this location.
3481/// * At some point, an ancestor might decide to remove this element (or an
3482/// intermediate ancestor) from the tree, which the ancestor does by calling
3483/// [deactivateChild] on itself. Deactivating the intermediate ancestor will
3484/// remove that element's render object from the render tree and add this
3485/// element to the [owner]'s list of inactive elements, causing the framework
3486/// to call [deactivate] on this element.
3487/// * At this point, the element is considered "inactive" and will not appear
3488/// on screen. An element can remain in the inactive state only until
3489/// the end of the current animation frame. At the end of the animation
3490/// frame, any elements that are still inactive will be unmounted.
3491/// * If the element gets reincorporated into the tree (e.g., because it or one
3492/// of its ancestors has a global key that is reused), the framework will
3493/// remove the element from the [owner]'s list of inactive elements, call
3494/// [activate] on the element, and reattach the element's render object to
3495/// the render tree. (At this point, the element is again considered "active"
3496/// and might appear on screen.)
3497/// * If the element does not get reincorporated into the tree by the end of
3498/// the current animation frame, the framework will call [unmount] on the
3499/// element.
3500/// * At this point, the element is considered "defunct" and will not be
3501/// incorporated into the tree in the future.
3502abstract class Element extends DiagnosticableTree implements BuildContext {
3503 /// Creates an element that uses the given widget as its configuration.
3504 ///
3505 /// Typically called by an override of [Widget.createElement].
3506 Element(Widget widget) : _widget = widget {
3507 assert(debugMaybeDispatchCreated('widgets', 'Element', this));
3508 }
3509
3510 Element? _parent;
3511 _NotificationNode? _notificationTree;
3512
3513 /// Compare two widgets for equality.
3514 ///
3515 /// When a widget is rebuilt with another that compares equal according
3516 /// to `operator ==`, it is assumed that the update is redundant and the
3517 /// work to update that branch of the tree is skipped.
3518 ///
3519 /// It is generally discouraged to override `operator ==` on any widget that
3520 /// has children, since a correct implementation would have to defer to the
3521 /// children's equality operator also, and that is an O(N²) operation: each
3522 /// child would need to itself walk all its children, each step of the tree.
3523 ///
3524 /// It is sometimes reasonable for a leaf widget (one with no children) to
3525 /// implement this method, if rebuilding the widget is known to be much more
3526 /// expensive than checking the widgets' parameters for equality and if the
3527 /// widget is expected to often be rebuilt with identical parameters.
3528 ///
3529 /// In general, however, it is more efficient to cache the widgets used
3530 /// in a build method if it is known that they will not change.
3531 @nonVirtual
3532 @override
3533 // ignore: avoid_equals_and_hash_code_on_mutable_classes, hash_and_equals
3534 bool operator ==(Object other) => identical(this, other);
3535
3536 /// Information set by parent to define where this child fits in its parent's
3537 /// child list.
3538 ///
3539 /// A child widget's slot is determined when the parent's [updateChild] method
3540 /// is called to inflate the child widget. See [RenderObjectElement] for more
3541 /// details on slots.
3542 Object? get slot => _slot;
3543 Object? _slot;
3544
3545 /// An integer that is guaranteed to be greater than the parent's, if any.
3546 /// The element at the root of the tree must have a depth greater than 0.
3547 int get depth {
3548 assert(() {
3549 if (_lifecycleState == _ElementLifecycle.initial) {
3550 throw FlutterError('Depth is only available when element has been mounted.');
3551 }
3552 return true;
3553 }());
3554 return _depth;
3555 }
3556
3557 late int _depth;
3558
3559 /// Returns result < 0 when [a] < [b], result == 0 when [a] == [b], result > 0
3560 /// when [a] > [b].
3561 static int _sort(Element a, Element b) {
3562 final int diff = a.depth - b.depth;
3563 // If depths are not equal, return the difference.
3564 if (diff != 0) {
3565 return diff;
3566 }
3567 // If the `dirty` values are not equal, sort with non-dirty elements being
3568 // less than dirty elements.
3569 final bool isBDirty = b.dirty;
3570 if (a.dirty != isBDirty) {
3571 return isBDirty ? -1 : 1;
3572 }
3573 // Otherwise, `depth`s and `dirty`s are equal.
3574 return 0;
3575 }
3576
3577 // Return a numeric encoding of the specific `Element` concrete subtype.
3578 // This is used in `Element.updateChild` to determine if a hot reload modified the
3579 // superclass of a mounted element's configuration. The encoding of each `Element`
3580 // must match the corresponding `Widget` encoding in `Widget._debugConcreteSubtype`.
3581 static int _debugConcreteSubtype(Element element) {
3582 return element is StatefulElement
3583 ? 1
3584 : element is StatelessElement
3585 ? 2
3586 : 0;
3587 }
3588
3589 /// The configuration for this element.
3590 ///
3591 /// Avoid overriding this field on [Element] subtypes to provide a more
3592 /// specific widget type (i.e. [StatelessElement] and [StatelessWidget]).
3593 /// Instead, cast at any call sites where the more specific type is required.
3594 /// This avoids significant cast overhead on the getter which is accessed
3595 /// throughout the framework internals during the build phase - and for which
3596 /// the more specific type information is not used.
3597 @override
3598 Widget get widget => _widget!;
3599 Widget? _widget;
3600
3601 @override
3602 bool get mounted => _widget != null;
3603
3604 /// Returns true if the Element is defunct.
3605 ///
3606 /// This getter always returns false in profile and release builds.
3607 /// See the lifecycle documentation for [Element] for additional information.
3608 bool get debugIsDefunct {
3609 bool isDefunct = false;
3610 assert(() {
3611 isDefunct = _lifecycleState == _ElementLifecycle.defunct;
3612 return true;
3613 }());
3614 return isDefunct;
3615 }
3616
3617 /// Returns true if the Element is active.
3618 ///
3619 /// This getter always returns false in profile and release builds.
3620 /// See the lifecycle documentation for [Element] for additional information.
3621 bool get debugIsActive {
3622 bool isActive = false;
3623 assert(() {
3624 isActive = _lifecycleState == _ElementLifecycle.active;
3625 return true;
3626 }());
3627 return isActive;
3628 }
3629
3630 /// The object that manages the lifecycle of this element.
3631 @override
3632 BuildOwner? get owner => _owner;
3633 BuildOwner? _owner;
3634
3635 /// A [BuildScope] whose dirty [Element]s can only be rebuilt by
3636 /// [BuildOwner.buildScope] calls whose `context` argument is an [Element]
3637 /// within this [BuildScope].
3638 ///
3639 /// The getter typically is only safe to access when this [Element] is [mounted].
3640 ///
3641 /// The default implementation returns the parent [Element]'s [buildScope],
3642 /// as in most cases an [Element] is ready to rebuild as soon as its ancestors
3643 /// are no longer dirty. One notable exception is [LayoutBuilder]'s
3644 /// descendants, which must not rebuild until the incoming constraints become
3645 /// available. [LayoutBuilder]'s [Element] overrides [buildScope] to make none
3646 /// of its descendants can rebuild until the incoming constraints are known.
3647 ///
3648 /// If you choose to override this getter to establish your own [BuildScope],
3649 /// to flush the dirty [Element]s in the [BuildScope] you need to manually call
3650 /// [BuildOwner.buildScope] with the root [Element] of your [BuildScope] when
3651 /// appropriate, as the Flutter framework does not try to register or manage
3652 /// custom [BuildScope]s.
3653 ///
3654 /// Always return the same [BuildScope] instance if you override this getter.
3655 /// Changing the value returned by this getter at runtime is not
3656 /// supported.
3657 ///
3658 /// The [updateChild] method ignores [buildScope]: if the parent [Element]
3659 /// calls [updateChild] on a child with a different [BuildScope], the child may
3660 /// still rebuild.
3661 ///
3662 /// See also:
3663 ///
3664 /// * [LayoutBuilder], a widget that establishes a custom [BuildScope].
3665 BuildScope get buildScope => _parentBuildScope!;
3666 // The cached value of the parent Element's build scope. The cache is updated
3667 // when this Element mounts or reparents.
3668 BuildScope? _parentBuildScope;
3669
3670 /// {@template flutter.widgets.Element.reassemble}
3671 /// Called whenever the application is reassembled during debugging, for
3672 /// example during hot reload.
3673 ///
3674 /// This method should rerun any initialization logic that depends on global
3675 /// state, for example, image loading from asset bundles (since the asset
3676 /// bundle may have changed).
3677 ///
3678 /// This function will only be called during development. In release builds,
3679 /// the `ext.flutter.reassemble` hook is not available, and so this code will
3680 /// never execute.
3681 ///
3682 /// Implementers should not rely on any ordering for hot reload source update,
3683 /// reassemble, and build methods after a hot reload has been initiated. It is
3684 /// possible that a [Timer] (e.g. an [Animation]) or a debugging session
3685 /// attached to the isolate could trigger a build with reloaded code _before_
3686 /// reassemble is called. Code that expects preconditions to be set by
3687 /// reassemble after a hot reload must be resilient to being called out of
3688 /// order, e.g. by fizzling instead of throwing. That said, once reassemble is
3689 /// called, build will be called after it at least once.
3690 /// {@endtemplate}
3691 ///
3692 /// See also:
3693 ///
3694 /// * [State.reassemble]
3695 /// * [BindingBase.reassembleApplication]
3696 /// * [Image], which uses this to reload images.
3697 @mustCallSuper
3698 @protected
3699 void reassemble() {
3700 markNeedsBuild();
3701 visitChildren((Element child) {
3702 child.reassemble();
3703 });
3704 }
3705
3706 bool _debugIsDescendantOf(Element target) {
3707 Element? element = this;
3708 while (element != null && element.depth > target.depth) {
3709 element = element._parent;
3710 }
3711 return element == target;
3712 }
3713
3714 /// The render object at (or below) this location in the tree.
3715 ///
3716 /// If this object is a [RenderObjectElement], the render object is the one at
3717 /// this location in the tree. Otherwise, this getter will walk down the tree
3718 /// until it finds a [RenderObjectElement].
3719 ///
3720 /// Some locations in the tree are not backed by a render object. In those
3721 /// cases, this getter returns null. This can happen, if the element is
3722 /// located outside of a [View] since only the element subtree rooted in a
3723 /// view has a render tree associated with it.
3724 RenderObject? get renderObject {
3725 Element? current = this;
3726 while (current != null) {
3727 if (current._lifecycleState == _ElementLifecycle.defunct) {
3728 break;
3729 } else if (current is RenderObjectElement) {
3730 return current.renderObject;
3731 } else {
3732 current = current.renderObjectAttachingChild;
3733 }
3734 }
3735 return null;
3736 }
3737
3738 /// Returns the child of this [Element] that will insert a [RenderObject] into
3739 /// an ancestor of this Element to construct the render tree.
3740 ///
3741 /// Returns null if this Element doesn't have any children who need to attach
3742 /// a [RenderObject] to an ancestor of this [Element]. A [RenderObjectElement]
3743 /// will therefore return null because its children insert their
3744 /// [RenderObject]s into the [RenderObjectElement] itself and not into an
3745 /// ancestor of the [RenderObjectElement].
3746 ///
3747 /// Furthermore, this may return null for [Element]s that hoist their own
3748 /// independent render tree and do not extend the ancestor render tree.
3749 @protected
3750 Element? get renderObjectAttachingChild {
3751 Element? next;
3752 visitChildren((Element child) {
3753 assert(next == null); // This verifies that there's only one child.
3754 next = child;
3755 });
3756 return next;
3757 }
3758
3759 @override
3760 List<DiagnosticsNode> describeMissingAncestor({required Type expectedAncestorType}) {
3761 final List<DiagnosticsNode> information = <DiagnosticsNode>[];
3762 final List<Element> ancestors = <Element>[];
3763 visitAncestorElements((Element element) {
3764 ancestors.add(element);
3765 return true;
3766 });
3767
3768 information.add(
3769 DiagnosticsProperty<Element>(
3770 'The specific widget that could not find a $expectedAncestorType ancestor was',
3771 this,
3772 style: DiagnosticsTreeStyle.errorProperty,
3773 ),
3774 );
3775
3776 if (ancestors.isNotEmpty) {
3777 information.add(describeElements('The ancestors of this widget were', ancestors));
3778 } else {
3779 information.add(
3780 ErrorDescription(
3781 'This widget is the root of the tree, so it has no '
3782 'ancestors, let alone a "$expectedAncestorType" ancestor.',
3783 ),
3784 );
3785 }
3786 return information;
3787 }
3788
3789 /// Returns a list of [Element]s from the current build context to the error report.
3790 static DiagnosticsNode describeElements(String name, Iterable<Element> elements) {
3791 return DiagnosticsBlock(
3792 name: name,
3793 children: elements
3794 .map<DiagnosticsNode>((Element element) => DiagnosticsProperty<Element>('', element))
3795 .toList(),
3796 allowTruncate: true,
3797 );
3798 }
3799
3800 @override
3801 DiagnosticsNode describeElement(
3802 String name, {
3803 DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
3804 }) {
3805 return DiagnosticsProperty<Element>(name, this, style: style);
3806 }
3807
3808 @override
3809 DiagnosticsNode describeWidget(
3810 String name, {
3811 DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
3812 }) {
3813 return DiagnosticsProperty<Element>(name, this, style: style);
3814 }
3815
3816 @override
3817 DiagnosticsNode describeOwnershipChain(String name) {
3818 // TODO(jacobr): make this structured so clients can support clicks on
3819 // individual entries. For example, is this an iterable with arrows as
3820 // separators?
3821 return StringProperty(name, debugGetCreatorChain(10));
3822 }
3823
3824 // This is used to verify that Element objects move through life in an
3825 // orderly fashion.
3826 _ElementLifecycle _lifecycleState = _ElementLifecycle.initial;
3827
3828 /// Calls the argument for each child. Must be overridden by subclasses that
3829 /// support having children.
3830 ///
3831 /// There is no guaranteed order in which the children will be visited, though
3832 /// it should be consistent over time.
3833 ///
3834 /// Calling this during build is dangerous: the child list might still be
3835 /// being updated at that point, so the children might not be constructed yet,
3836 /// or might be old children that are going to be replaced. This method should
3837 /// only be called if it is provable that the children are available.
3838 void visitChildren(ElementVisitor visitor) {}
3839
3840 /// Calls the argument for each child considered onstage.
3841 ///
3842 /// Classes like [Offstage] and [Overlay] override this method to hide their
3843 /// children.
3844 ///
3845 /// Being onstage affects the element's discoverability during testing when
3846 /// you use Flutter's [Finder] objects. For example, when you instruct the
3847 /// test framework to tap on a widget, by default the finder will look for
3848 /// onstage elements and ignore the offstage ones.
3849 ///
3850 /// The default implementation defers to [visitChildren] and therefore treats
3851 /// the element as onstage.
3852 ///
3853 /// See also:
3854 ///
3855 /// * [Offstage] widget that hides its children.
3856 /// * [Finder] that skips offstage widgets by default.
3857 /// * [RenderObject.visitChildrenForSemantics], in contrast to this method,
3858 /// designed specifically for excluding parts of the UI from the semantics
3859 /// tree.
3860 void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
3861
3862 /// Wrapper around [visitChildren] for [BuildContext].
3863 @override
3864 void visitChildElements(ElementVisitor visitor) {
3865 assert(() {
3866 if (owner == null || !owner!._debugStateLocked) {
3867 return true;
3868 }
3869 throw FlutterError.fromParts(<DiagnosticsNode>[
3870 ErrorSummary('visitChildElements() called during build.'),
3871 ErrorDescription(
3872 "The BuildContext.visitChildElements() method can't be called during "
3873 'build because the child list is still being updated at that point, '
3874 'so the children might not be constructed yet, or might be old children '
3875 'that are going to be replaced.',
3876 ),
3877 ]);
3878 }());
3879 visitChildren(visitor);
3880 }
3881
3882 /// Update the given child with the given new configuration.
3883 ///
3884 /// This method is the core of the widgets system. It is called each time we
3885 /// are to add, update, or remove a child based on an updated configuration.
3886 ///
3887 /// The `newSlot` argument specifies the new value for this element's [slot].
3888 ///
3889 /// If the `child` is null, and the `newWidget` is not null, then we have a new
3890 /// child for which we need to create an [Element], configured with `newWidget`.
3891 ///
3892 /// If the `newWidget` is null, and the `child` is not null, then we need to
3893 /// remove it because it no longer has a configuration.
3894 ///
3895 /// If neither are null, then we need to update the `child`'s configuration to
3896 /// be the new configuration given by `newWidget`. If `newWidget` can be given
3897 /// to the existing child (as determined by [Widget.canUpdate]), then it is so
3898 /// given. Otherwise, the old child needs to be disposed and a new child
3899 /// created for the new configuration.
3900 ///
3901 /// If both are null, then we don't have a child and won't have a child, so we
3902 /// do nothing.
3903 ///
3904 /// The [updateChild] method returns the new child, if it had to create one,
3905 /// or the child that was passed in, if it just had to update the child, or
3906 /// null, if it removed the child and did not replace it.
3907 ///
3908 /// The following table summarizes the above:
3909 ///
3910 /// | | **newWidget == null** | **newWidget != null** |
3911 /// | :-----------------: | :--------------------- | :---------------------- |
3912 /// | **child == null** | Returns null. | Returns new [Element]. |
3913 /// | **child != null** | Old child is removed, returns null. | Old child updated if possible, returns child or new [Element]. |
3914 ///
3915 /// The `newSlot` argument is used only if `newWidget` is not null. If `child`
3916 /// is null (or if the old child cannot be updated), then the `newSlot` is
3917 /// given to the new [Element] that is created for the child, via
3918 /// [inflateWidget]. If `child` is not null (and the old child _can_ be
3919 /// updated), then the `newSlot` is given to [updateSlotForChild] to update
3920 /// its slot, in case it has moved around since it was last built.
3921 ///
3922 /// See the [RenderObjectElement] documentation for more information on slots.
3923 @protected
3924 @pragma('dart2js:tryInline')
3925 @pragma('vm:prefer-inline')
3926 @pragma('wasm:prefer-inline')
3927 Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
3928 if (newWidget == null) {
3929 if (child != null) {
3930 deactivateChild(child);
3931 }
3932 return null;
3933 }
3934
3935 final Element newChild;
3936 if (child != null) {
3937 bool hasSameSuperclass = true;
3938 // When the type of a widget is changed between Stateful and Stateless via
3939 // hot reload, the element tree will end up in a partially invalid state.
3940 // That is, if the widget was a StatefulWidget and is now a StatelessWidget,
3941 // then the element tree currently contains a StatefulElement that is incorrectly
3942 // referencing a StatelessWidget (and likewise with StatelessElement).
3943 //
3944 // To avoid crashing due to type errors, we need to gently guide the invalid
3945 // element out of the tree. To do so, we ensure that the `hasSameSuperclass` condition
3946 // returns false which prevents us from trying to update the existing element
3947 // incorrectly.
3948 //
3949 // For the case where the widget becomes Stateful, we also need to avoid
3950 // accessing `StatelessElement.widget` as the cast on the getter will
3951 // cause a type error to be thrown. Here we avoid that by short-circuiting
3952 // the `Widget.canUpdate` check once `hasSameSuperclass` is false.
3953 assert(() {
3954 final int oldElementClass = Element._debugConcreteSubtype(child);
3955 final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
3956 hasSameSuperclass = oldElementClass == newWidgetClass;
3957 return true;
3958 }());
3959 if (hasSameSuperclass && child.widget == newWidget) {
3960 // We don't insert a timeline event here, because otherwise it's
3961 // confusing that widgets that "don't update" (because they didn't
3962 // change) get "charged" on the timeline.
3963 if (child.slot != newSlot) {
3964 updateSlotForChild(child, newSlot);
3965 }
3966 newChild = child;
3967 } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
3968 if (child.slot != newSlot) {
3969 updateSlotForChild(child, newSlot);
3970 }
3971 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
3972 if (isTimelineTracked) {
3973 Map<String, String>? debugTimelineArguments;
3974 assert(() {
3975 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
3976 debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
3977 }
3978 return true;
3979 }());
3980 FlutterTimeline.startSync('${newWidget.runtimeType}', arguments: debugTimelineArguments);
3981 }
3982 child.update(newWidget);
3983 if (isTimelineTracked) {
3984 FlutterTimeline.finishSync();
3985 }
3986 assert(child.widget == newWidget);
3987 assert(() {
3988 child.owner!._debugElementWasRebuilt(child);
3989 return true;
3990 }());
3991 newChild = child;
3992 } else {
3993 deactivateChild(child);
3994 assert(child._parent == null);
3995 // The [debugProfileBuildsEnabled] code for this branch is inside
3996 // [inflateWidget], since some [Element]s call [inflateWidget] directly
3997 // instead of going through [updateChild].
3998 newChild = inflateWidget(newWidget, newSlot);
3999 }
4000 } else {
4001 // The [debugProfileBuildsEnabled] code for this branch is inside
4002 // [inflateWidget], since some [Element]s call [inflateWidget] directly
4003 // instead of going through [updateChild].
4004 newChild = inflateWidget(newWidget, newSlot);
4005 }
4006
4007 assert(() {
4008 if (child != null) {
4009 _debugRemoveGlobalKeyReservation(child);
4010 }
4011 final Key? key = newWidget.key;
4012 if (key is GlobalKey) {
4013 assert(owner != null);
4014 owner!._debugReserveGlobalKeyFor(this, newChild, key);
4015 }
4016 return true;
4017 }());
4018
4019 return newChild;
4020 }
4021
4022 /// Updates the children of this element to use new widgets.
4023 ///
4024 /// Attempts to update the given old children list using the given new
4025 /// widgets, removing obsolete elements and introducing new ones as necessary,
4026 /// and then returns the new child list.
4027 ///
4028 /// During this function the `oldChildren` list must not be modified. If the
4029 /// caller wishes to remove elements from `oldChildren` reentrantly while
4030 /// this function is on the stack, the caller can supply a `forgottenChildren`
4031 /// argument, which can be modified while this function is on the stack.
4032 /// Whenever this function reads from `oldChildren`, this function first
4033 /// checks whether the child is in `forgottenChildren`. If it is, the function
4034 /// acts as if the child was not in `oldChildren`.
4035 ///
4036 /// This function is a convenience wrapper around [updateChild], which updates
4037 /// each individual child. If `slots` is non-null, the value for the `newSlot`
4038 /// argument of [updateChild] is retrieved from that list using the index that
4039 /// the currently processed `child` corresponds to in the `newWidgets` list
4040 /// (`newWidgets` and `slots` must have the same length). If `slots` is null,
4041 /// an [IndexedSlot<Element>] is used as the value for the `newSlot` argument.
4042 /// In that case, [IndexedSlot.index] is set to the index that the currently
4043 /// processed `child` corresponds to in the `newWidgets` list and
4044 /// [IndexedSlot.value] is set to the [Element] of the previous widget in that
4045 /// list (or null if it is the first child).
4046 ///
4047 /// When the [slot] value of an [Element] changes, its
4048 /// associated [renderObject] needs to move to a new position in the child
4049 /// list of its parents. If that [RenderObject] organizes its children in a
4050 /// linked list (as is done by the [ContainerRenderObjectMixin]) this can
4051 /// be implemented by re-inserting the child [RenderObject] into the
4052 /// list after the [RenderObject] associated with the [Element] provided as
4053 /// [IndexedSlot.value] in the [slot] object.
4054 ///
4055 /// Using the previous sibling as a [slot] is not enough, though, because
4056 /// child [RenderObject]s are only moved around when the [slot] of their
4057 /// associated [RenderObjectElement]s is updated. When the order of child
4058 /// [Element]s is changed, some elements in the list may move to a new index
4059 /// but still have the same previous sibling. For example, when
4060 /// `[e1, e2, e3, e4]` is changed to `[e1, e3, e4, e2]` the element e4
4061 /// continues to have e3 as a previous sibling even though its index in the list
4062 /// has changed and its [RenderObject] needs to move to come before e2's
4063 /// [RenderObject]. In order to trigger this move, a new [slot] value needs to
4064 /// be assigned to its [Element] whenever its index in its
4065 /// parent's child list changes. Using an [IndexedSlot<Element>] achieves
4066 /// exactly that and also ensures that the underlying parent [RenderObject]
4067 /// knows where a child needs to move to in a linked list by providing its new
4068 /// previous sibling.
4069 @protected
4070 List<Element> updateChildren(
4071 List<Element> oldChildren,
4072 List<Widget> newWidgets, {
4073 Set<Element>? forgottenChildren,
4074 List<Object?>? slots,
4075 }) {
4076 assert(slots == null || newWidgets.length == slots.length);
4077
4078 Element? replaceWithNullIfForgotten(Element child) {
4079 return (forgottenChildren?.contains(child) ?? false) ? null : child;
4080 }
4081
4082 Object? slotFor(int newChildIndex, Element? previousChild) {
4083 return slots != null
4084 ? slots[newChildIndex]
4085 : IndexedSlot<Element?>(newChildIndex, previousChild);
4086 }
4087
4088 // This attempts to diff the new child list (newWidgets) with
4089 // the old child list (oldChildren), and produce a new list of elements to
4090 // be the new list of child elements of this element. The called of this
4091 // method is expected to update this render object accordingly.
4092
4093 // The cases it tries to optimize for are:
4094 // - the old list is empty
4095 // - the lists are identical
4096 // - there is an insertion or removal of one or more widgets in
4097 // only one place in the list
4098 // If a widget with a key is in both lists, it will be synced.
4099 // Widgets without keys might be synced but there is no guarantee.
4100
4101 // The general approach is to sync the entire new list backwards, as follows:
4102 // 1. Walk the lists from the top, syncing nodes, until you no longer have
4103 // matching nodes.
4104 // 2. Walk the lists from the bottom, without syncing nodes, until you no
4105 // longer have matching nodes. We'll sync these nodes at the end. We
4106 // don't sync them now because we want to sync all the nodes in order
4107 // from beginning to end.
4108 // At this point we narrowed the old and new lists to the point
4109 // where the nodes no longer match.
4110 // 3. Walk the narrowed part of the old list to get the list of
4111 // keys and sync null with non-keyed items.
4112 // 4. Walk the narrowed part of the new list forwards:
4113 // * Sync non-keyed items with null
4114 // * Sync keyed items with the source if it exists, else with null.
4115 // 5. Walk the bottom of the list again, syncing the nodes.
4116 // 6. Sync null with any items in the list of keys that are still
4117 // mounted.
4118
4119 int newChildrenTop = 0;
4120 int oldChildrenTop = 0;
4121 int newChildrenBottom = newWidgets.length - 1;
4122 int oldChildrenBottom = oldChildren.length - 1;
4123
4124 final List<Element> newChildren = List<Element>.filled(
4125 newWidgets.length,
4126 _NullElement.instance,
4127 );
4128
4129 Element? previousChild;
4130
4131 // Update the top of the list.
4132 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4133 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
4134 final Widget newWidget = newWidgets[newChildrenTop];
4135 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
4136 if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget)) {
4137 break;
4138 }
4139 final Element newChild = updateChild(
4140 oldChild,
4141 newWidget,
4142 slotFor(newChildrenTop, previousChild),
4143 )!;
4144 assert(newChild._lifecycleState == _ElementLifecycle.active);
4145 newChildren[newChildrenTop] = newChild;
4146 previousChild = newChild;
4147 newChildrenTop += 1;
4148 oldChildrenTop += 1;
4149 }
4150
4151 // Scan the bottom of the list.
4152 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4153 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);
4154 final Widget newWidget = newWidgets[newChildrenBottom];
4155 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
4156 if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget)) {
4157 break;
4158 }
4159 oldChildrenBottom -= 1;
4160 newChildrenBottom -= 1;
4161 }
4162
4163 // Scan the old children in the middle of the list.
4164 final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
4165 Map<Key, Element>? oldKeyedChildren;
4166 if (haveOldChildren) {
4167 oldKeyedChildren = <Key, Element>{};
4168 while (oldChildrenTop <= oldChildrenBottom) {
4169 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
4170 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
4171 if (oldChild != null) {
4172 if (oldChild.widget.key != null) {
4173 oldKeyedChildren[oldChild.widget.key!] = oldChild;
4174 } else {
4175 deactivateChild(oldChild);
4176 }
4177 }
4178 oldChildrenTop += 1;
4179 }
4180 }
4181
4182 // Update the middle of the list.
4183 while (newChildrenTop <= newChildrenBottom) {
4184 Element? oldChild;
4185 final Widget newWidget = newWidgets[newChildrenTop];
4186 if (haveOldChildren) {
4187 final Key? key = newWidget.key;
4188 if (key != null) {
4189 oldChild = oldKeyedChildren![key];
4190 if (oldChild != null) {
4191 if (Widget.canUpdate(oldChild.widget, newWidget)) {
4192 // we found a match!
4193 // remove it from oldKeyedChildren so we don't unsync it later
4194 oldKeyedChildren.remove(key);
4195 } else {
4196 // Not a match, let's pretend we didn't see it for now.
4197 oldChild = null;
4198 }
4199 }
4200 }
4201 }
4202 assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));
4203 final Element newChild = updateChild(
4204 oldChild,
4205 newWidget,
4206 slotFor(newChildrenTop, previousChild),
4207 )!;
4208 assert(newChild._lifecycleState == _ElementLifecycle.active);
4209 assert(
4210 oldChild == newChild ||
4211 oldChild == null ||
4212 oldChild._lifecycleState != _ElementLifecycle.active,
4213 );
4214 newChildren[newChildrenTop] = newChild;
4215 previousChild = newChild;
4216 newChildrenTop += 1;
4217 }
4218
4219 // We've scanned the whole list.
4220 assert(oldChildrenTop == oldChildrenBottom + 1);
4221 assert(newChildrenTop == newChildrenBottom + 1);
4222 assert(newWidgets.length - newChildrenTop == oldChildren.length - oldChildrenTop);
4223 newChildrenBottom = newWidgets.length - 1;
4224 oldChildrenBottom = oldChildren.length - 1;
4225
4226 // Update the bottom of the list.
4227 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4228 final Element oldChild = oldChildren[oldChildrenTop];
4229 assert(replaceWithNullIfForgotten(oldChild) != null);
4230 assert(oldChild._lifecycleState == _ElementLifecycle.active);
4231 final Widget newWidget = newWidgets[newChildrenTop];
4232 assert(Widget.canUpdate(oldChild.widget, newWidget));
4233 final Element newChild = updateChild(
4234 oldChild,
4235 newWidget,
4236 slotFor(newChildrenTop, previousChild),
4237 )!;
4238 assert(newChild._lifecycleState == _ElementLifecycle.active);
4239 assert(oldChild == newChild || oldChild._lifecycleState != _ElementLifecycle.active);
4240 newChildren[newChildrenTop] = newChild;
4241 previousChild = newChild;
4242 newChildrenTop += 1;
4243 oldChildrenTop += 1;
4244 }
4245
4246 // Clean up any of the remaining middle nodes from the old list.
4247 if (haveOldChildren && oldKeyedChildren!.isNotEmpty) {
4248 for (final Element oldChild in oldKeyedChildren.values) {
4249 if (forgottenChildren == null || !forgottenChildren.contains(oldChild)) {
4250 deactivateChild(oldChild);
4251 }
4252 }
4253 }
4254 assert(newChildren.every((Element element) => element is! _NullElement));
4255 return newChildren;
4256 }
4257
4258 /// Add this element to the tree in the given slot of the given parent.
4259 ///
4260 /// The framework calls this function when a newly created element is added to
4261 /// the tree for the first time. Use this method to initialize state that
4262 /// depends on having a parent. State that is independent of the parent can
4263 /// more easily be initialized in the constructor.
4264 ///
4265 /// This method transitions the element from the "initial" lifecycle state to
4266 /// the "active" lifecycle state.
4267 ///
4268 /// Subclasses that override this method are likely to want to also override
4269 /// [update], [visitChildren], [RenderObjectElement.insertRenderObjectChild],
4270 /// [RenderObjectElement.moveRenderObjectChild], and
4271 /// [RenderObjectElement.removeRenderObjectChild].
4272 ///
4273 /// Implementations of this method should start with a call to the inherited
4274 /// method, as in `super.mount(parent, newSlot)`.
4275 @mustCallSuper
4276 void mount(Element? parent, Object? newSlot) {
4277 assert(
4278 _lifecycleState == _ElementLifecycle.initial,
4279 'This element is no longer in its initial state (${_lifecycleState.name})',
4280 );
4281 assert(
4282 _parent == null,
4283 "This element already has a parent ($_parent) and it shouldn't have one yet.",
4284 );
4285 assert(
4286 parent == null || parent._lifecycleState == _ElementLifecycle.active,
4287 'Parent ($parent) should be null or in the active state (${parent._lifecycleState.name})',
4288 );
4289 assert(slot == null, "This element already has a slot ($slot) and it shouldn't");
4290 _parent = parent;
4291 _slot = newSlot;
4292 _lifecycleState = _ElementLifecycle.active;
4293 _depth = 1 + (_parent?.depth ?? 0);
4294 if (parent != null) {
4295 // Only assign ownership if the parent is non-null. If parent is null
4296 // (the root node), the owner should have already been assigned.
4297 // See RootRenderObjectElement.assignOwner().
4298 _owner = parent.owner;
4299 _parentBuildScope = parent.buildScope;
4300 }
4301 assert(owner != null);
4302 final Key? key = widget.key;
4303 if (key is GlobalKey) {
4304 owner!._registerGlobalKey(key, this);
4305 }
4306 _updateInheritance();
4307 attachNotificationTree();
4308 }
4309
4310 void _debugRemoveGlobalKeyReservation(Element child) {
4311 assert(owner != null);
4312 owner!._debugRemoveGlobalKeyReservationFor(this, child);
4313 }
4314
4315 /// Change the widget used to configure this element.
4316 ///
4317 /// The framework calls this function when the parent wishes to use a
4318 /// different widget to configure this element. The new widget is guaranteed
4319 /// to have the same [runtimeType] as the old widget.
4320 ///
4321 /// This function is called only during the "active" lifecycle state.
4322 @mustCallSuper
4323 void update(covariant Widget newWidget) {
4324 // This code is hot when hot reloading, so we try to
4325 // only call _AssertionError._evaluateAssertion once.
4326 assert(
4327 _lifecycleState == _ElementLifecycle.active &&
4328 newWidget != widget &&
4329 Widget.canUpdate(widget, newWidget),
4330 );
4331 // This Element was told to update and we can now release all the global key
4332 // reservations of forgotten children. We cannot do this earlier because the
4333 // forgotten children still represent global key duplications if the element
4334 // never updates (the forgotten children are not removed from the tree
4335 // until the call to update happens)
4336 assert(() {
4337 _debugForgottenChildrenWithGlobalKey?.forEach(_debugRemoveGlobalKeyReservation);
4338 _debugForgottenChildrenWithGlobalKey?.clear();
4339 return true;
4340 }());
4341 _widget = newWidget;
4342 }
4343
4344 /// Change the slot that the given child occupies in its parent.
4345 ///
4346 /// Called by [MultiChildRenderObjectElement], and other [RenderObjectElement]
4347 /// subclasses that have multiple children, when child moves from one position
4348 /// to another in this element's child list.
4349 @protected
4350 void updateSlotForChild(Element child, Object? newSlot) {
4351 assert(_lifecycleState == _ElementLifecycle.active);
4352 assert(child._parent == this);
4353 void visit(Element element) {
4354 element.updateSlot(newSlot);
4355 final Element? descendant = element.renderObjectAttachingChild;
4356 if (descendant != null) {
4357 visit(descendant);
4358 }
4359 }
4360
4361 visit(child);
4362 }
4363
4364 /// Called by [updateSlotForChild] when the framework needs to change the slot
4365 /// that this [Element] occupies in its ancestor.
4366 @protected
4367 @mustCallSuper
4368 void updateSlot(Object? newSlot) {
4369 assert(_lifecycleState == _ElementLifecycle.active);
4370 assert(_parent != null);
4371 assert(_parent!._lifecycleState == _ElementLifecycle.active);
4372 _slot = newSlot;
4373 }
4374
4375 void _updateDepth(int parentDepth) {
4376 final int expectedDepth = parentDepth + 1;
4377 if (_depth < expectedDepth) {
4378 _depth = expectedDepth;
4379 visitChildren((Element child) {
4380 child._updateDepth(expectedDepth);
4381 });
4382 }
4383 }
4384
4385 void _updateBuildScopeRecursively() {
4386 if (identical(buildScope, _parent?.buildScope)) {
4387 return;
4388 }
4389 // Unset the _inDirtyList flag so this Element can be added to the dirty list
4390 // of the new build scope if it's dirty.
4391 _inDirtyList = false;
4392 _parentBuildScope = _parent?.buildScope;
4393 visitChildren((Element child) {
4394 child._updateBuildScopeRecursively();
4395 });
4396 }
4397
4398 /// Remove [renderObject] from the render tree.
4399 ///
4400 /// The default implementation of this function calls
4401 /// [detachRenderObject] recursively on each child. The
4402 /// [RenderObjectElement.detachRenderObject] override does the actual work of
4403 /// removing [renderObject] from the render tree.
4404 ///
4405 /// This is called by [deactivateChild].
4406 void detachRenderObject() {
4407 visitChildren((Element child) {
4408 child.detachRenderObject();
4409 });
4410 _slot = null;
4411 }
4412
4413 /// Add [renderObject] to the render tree at the location specified by `newSlot`.
4414 ///
4415 /// The default implementation of this function calls
4416 /// [attachRenderObject] recursively on each child. The
4417 /// [RenderObjectElement.attachRenderObject] override does the actual work of
4418 /// adding [renderObject] to the render tree.
4419 ///
4420 /// The `newSlot` argument specifies the new value for this element's [slot].
4421 void attachRenderObject(Object? newSlot) {
4422 assert(slot == null);
4423 visitChildren((Element child) {
4424 child.attachRenderObject(newSlot);
4425 });
4426 _slot = newSlot;
4427 }
4428
4429 Element? _retakeInactiveElement(GlobalKey key, Widget newWidget) {
4430 // The "inactivity" of the element being retaken here may be forward-looking: if
4431 // we are taking an element with a GlobalKey from an element that currently has
4432 // it as a child, then we know that element will soon no longer have that
4433 // element as a child. The only way that assumption could be false is if the
4434 // global key is being duplicated, and we'll try to track that using the
4435 // _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans call below.
4436 final Element? element = key._currentElement;
4437 if (element == null) {
4438 return null;
4439 }
4440 if (!Widget.canUpdate(element.widget, newWidget)) {
4441 return null;
4442 }
4443 assert(() {
4444 if (debugPrintGlobalKeyedWidgetLifecycle) {
4445 debugPrint(
4446 'Attempting to take $element from ${element._parent ?? "inactive elements list"} to put in $this.',
4447 );
4448 }
4449 return true;
4450 }());
4451 final Element? parent = element._parent;
4452 if (parent != null) {
4453 assert(() {
4454 if (parent == this) {
4455 throw FlutterError.fromParts(<DiagnosticsNode>[
4456 ErrorSummary("A GlobalKey was used multiple times inside one widget's child list."),
4457 DiagnosticsProperty<GlobalKey>('The offending GlobalKey was', key),
4458 parent.describeElement('The parent of the widgets with that key was'),
4459 element.describeElement('The first child to get instantiated with that key became'),
4460 DiagnosticsProperty<Widget>(
4461 'The second child that was to be instantiated with that key was',
4462 widget,
4463 style: DiagnosticsTreeStyle.errorProperty,
4464 ),
4465 ErrorDescription(
4466 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
4467 ),
4468 ]);
4469 }
4470 parent.owner!._debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(
4471 parent,
4472 key,
4473 );
4474 return true;
4475 }());
4476 parent.forgetChild(element);
4477 parent.deactivateChild(element);
4478 }
4479 assert(element._parent == null);
4480 owner!._inactiveElements.remove(element);
4481 return element;
4482 }
4483
4484 /// Create an element for the given widget and add it as a child of this
4485 /// element in the given slot.
4486 ///
4487 /// This method is typically called by [updateChild] but can be called
4488 /// directly by subclasses that need finer-grained control over creating
4489 /// elements.
4490 ///
4491 /// If the given widget has a global key and an element already exists that
4492 /// has a widget with that global key, this function will reuse that element
4493 /// (potentially grafting it from another location in the tree or reactivating
4494 /// it from the list of inactive elements) rather than creating a new element.
4495 ///
4496 /// The `newSlot` argument specifies the new value for this element's [slot].
4497 ///
4498 /// The element returned by this function will already have been mounted and
4499 /// will be in the "active" lifecycle state.
4500 @protected
4501 @pragma('dart2js:tryInline')
4502 @pragma('vm:prefer-inline')
4503 @pragma('wasm:prefer-inline')
4504 Element inflateWidget(Widget newWidget, Object? newSlot) {
4505 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
4506 if (isTimelineTracked) {
4507 Map<String, String>? debugTimelineArguments;
4508 assert(() {
4509 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
4510 debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
4511 }
4512 return true;
4513 }());
4514 FlutterTimeline.startSync('${newWidget.runtimeType}', arguments: debugTimelineArguments);
4515 }
4516
4517 try {
4518 final Key? key = newWidget.key;
4519 if (key is GlobalKey) {
4520 final Element? newChild = _retakeInactiveElement(key, newWidget);
4521 if (newChild != null) {
4522 assert(newChild._parent == null);
4523 assert(() {
4524 _debugCheckForCycles(newChild);
4525 return true;
4526 }());
4527 try {
4528 newChild._activateWithParent(this, newSlot);
4529 } catch (_) {
4530 // Attempt to do some clean-up if activation fails to leave tree in a reasonable state.
4531 try {
4532 deactivateChild(newChild);
4533 } catch (_) {
4534 // Clean-up failed. Only surface original exception.
4535 }
4536 rethrow;
4537 }
4538 final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
4539 assert(newChild == updatedChild);
4540 return updatedChild!;
4541 }
4542 }
4543 final Element newChild = newWidget.createElement();
4544 assert(() {
4545 _debugCheckForCycles(newChild);
4546 return true;
4547 }());
4548 newChild.mount(this, newSlot);
4549 assert(newChild._lifecycleState == _ElementLifecycle.active);
4550
4551 return newChild;
4552 } finally {
4553 if (isTimelineTracked) {
4554 FlutterTimeline.finishSync();
4555 }
4556 }
4557 }
4558
4559 void _debugCheckForCycles(Element newChild) {
4560 assert(newChild._parent == null);
4561 assert(() {
4562 Element node = this;
4563 while (node._parent != null) {
4564 node = node._parent!;
4565 }
4566 assert(node != newChild); // indicates we are about to create a cycle
4567 return true;
4568 }());
4569 }
4570
4571 /// Move the given element to the list of inactive elements and detach its
4572 /// render object from the render tree.
4573 ///
4574 /// This method stops the given element from being a child of this element by
4575 /// detaching its render object from the render tree and moving the element to
4576 /// the list of inactive elements.
4577 ///
4578 /// This method (indirectly) calls [deactivate] on the child.
4579 ///
4580 /// The caller is responsible for removing the child from its child model.
4581 /// Typically [deactivateChild] is called by the element itself while it is
4582 /// updating its child model; however, during [GlobalKey] reparenting, the new
4583 /// parent proactively calls the old parent's [deactivateChild], first using
4584 /// [forgetChild] to cause the old parent to update its child model.
4585 @protected
4586 void deactivateChild(Element child) {
4587 assert(child._parent == this);
4588 child._parent = null;
4589 child.detachRenderObject();
4590 owner!._inactiveElements.add(child); // this eventually calls child.deactivate()
4591 assert(() {
4592 if (debugPrintGlobalKeyedWidgetLifecycle) {
4593 if (child.widget.key is GlobalKey) {
4594 debugPrint('Deactivated $child (keyed child of $this)');
4595 }
4596 }
4597 return true;
4598 }());
4599 }
4600
4601 // The children that have been forgotten by forgetChild. This will be used in
4602 // [update] to remove the global key reservations of forgotten children.
4603 //
4604 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
4605 // eliminate unused fields, but not their initializers.
4606 @_debugOnly
4607 final Set<Element>? _debugForgottenChildrenWithGlobalKey = kDebugMode ? HashSet<Element>() : null;
4608
4609 /// Remove the given child from the element's child list, in preparation for
4610 /// the child being reused elsewhere in the element tree.
4611 ///
4612 /// This updates the child model such that, e.g., [visitChildren] does not
4613 /// walk that child anymore.
4614 ///
4615 /// The element will still have a valid parent when this is called, and the
4616 /// child's [Element.slot] value will be valid in the context of that parent.
4617 /// After this is called, [deactivateChild] is called to sever the link to
4618 /// this object.
4619 ///
4620 /// The [update] is responsible for updating or creating the new child that
4621 /// will replace this [child].
4622 @protected
4623 @mustCallSuper
4624 void forgetChild(Element child) {
4625 // This method is called on the old parent when the given child (with a
4626 // global key) is given a new parent. We cannot remove the global key
4627 // reservation directly in this method because the forgotten child is not
4628 // removed from the tree until this Element is updated in [update]. If
4629 // [update] is never called, the forgotten child still represents a global
4630 // key duplication that we need to catch.
4631 assert(() {
4632 if (child.widget.key is GlobalKey) {
4633 _debugForgottenChildrenWithGlobalKey?.add(child);
4634 }
4635 return true;
4636 }());
4637 }
4638
4639 void _activateWithParent(Element parent, Object? newSlot) {
4640 assert(_lifecycleState == _ElementLifecycle.inactive);
4641 _parent = parent;
4642 _owner = parent.owner;
4643 assert(() {
4644 if (debugPrintGlobalKeyedWidgetLifecycle) {
4645 debugPrint('Reactivating $this (now child of $_parent).');
4646 }
4647 return true;
4648 }());
4649 _updateDepth(_parent!.depth);
4650 _updateBuildScopeRecursively();
4651 _activateRecursively(this);
4652 attachRenderObject(newSlot);
4653 assert(_lifecycleState == _ElementLifecycle.active);
4654 }
4655
4656 static void _activateRecursively(Element element) {
4657 assert(element._lifecycleState == _ElementLifecycle.inactive);
4658 element.activate();
4659 assert(element._lifecycleState == _ElementLifecycle.active);
4660 element.visitChildren(_activateRecursively);
4661 }
4662
4663 /// Transition from the "inactive" to the "active" lifecycle state.
4664 ///
4665 /// The framework calls this method when a previously deactivated element has
4666 /// been reincorporated into the tree. The framework does not call this method
4667 /// the first time an element becomes active (i.e., from the "initial"
4668 /// lifecycle state). Instead, the framework calls [mount] in that situation.
4669 ///
4670 /// See the lifecycle documentation for [Element] for additional information.
4671 ///
4672 /// Implementations of this method should start with a call to the inherited
4673 /// method, as in `super.activate()`.
4674 @mustCallSuper
4675 void activate() {
4676 assert(_lifecycleState == _ElementLifecycle.inactive);
4677 assert(owner != null);
4678 final bool hadDependencies =
4679 (_dependencies?.isNotEmpty ?? false) || _hadUnsatisfiedDependencies;
4680 _lifecycleState = _ElementLifecycle.active;
4681 // We unregistered our dependencies in deactivate, but never cleared the list.
4682 // Since we're going to be reused, let's clear our list now.
4683 _dependencies?.clear();
4684 _hadUnsatisfiedDependencies = false;
4685 _updateInheritance();
4686 attachNotificationTree();
4687 if (_dirty) {
4688 owner!.scheduleBuildFor(this);
4689 }
4690 if (hadDependencies) {
4691 didChangeDependencies();
4692 }
4693 }
4694
4695 /// Transition from the "active" to the "inactive" lifecycle state.
4696 ///
4697 /// The framework calls this method when a previously active element is moved
4698 /// to the list of inactive elements. While in the inactive state, the element
4699 /// will not appear on screen. The element can remain in the inactive state
4700 /// only until the end of the current animation frame. At the end of the
4701 /// animation frame, if the element has not be reactivated, the framework will
4702 /// unmount the element.
4703 ///
4704 /// This is (indirectly) called by [deactivateChild].
4705 ///
4706 /// See the lifecycle documentation for [Element] for additional information.
4707 ///
4708 /// Implementations of this method should end with a call to the inherited
4709 /// method, as in `super.deactivate()`.
4710 @mustCallSuper
4711 void deactivate() {
4712 assert(_lifecycleState == _ElementLifecycle.active);
4713 assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
4714 if (_dependencies?.isNotEmpty ?? false) {
4715 for (final InheritedElement dependency in _dependencies!) {
4716 dependency.removeDependent(this);
4717 }
4718 // For expediency, we don't actually clear the list here, even though it's
4719 // no longer representative of what we are registered with. If we never
4720 // get re-used, it doesn't matter. If we do, then we'll clear the list in
4721 // activate(). The benefit of this is that it allows Element's activate()
4722 // implementation to decide whether to rebuild based on whether we had
4723 // dependencies here.
4724 }
4725 _inheritedElements = null;
4726 _lifecycleState = _ElementLifecycle.inactive;
4727 }
4728
4729 /// Called, in debug mode, after children have been deactivated (see [deactivate]).
4730 ///
4731 /// This method is not called in release builds.
4732 @mustCallSuper
4733 void debugDeactivated() {
4734 assert(_lifecycleState == _ElementLifecycle.inactive);
4735 }
4736
4737 /// Transition from the "inactive" to the "defunct" lifecycle state.
4738 ///
4739 /// Called when the framework determines that an inactive element will never
4740 /// be reactivated. At the end of each animation frame, the framework calls
4741 /// [unmount] on any remaining inactive elements, preventing inactive elements
4742 /// from remaining inactive for longer than a single animation frame.
4743 ///
4744 /// After this function is called, the element will not be incorporated into
4745 /// the tree again.
4746 ///
4747 /// Any resources this element holds should be released at this point. For
4748 /// example, [RenderObjectElement.unmount] calls [RenderObject.dispose] and
4749 /// nulls out its reference to the render object.
4750 ///
4751 /// See the lifecycle documentation for [Element] for additional information.
4752 ///
4753 /// Implementations of this method should end with a call to the inherited
4754 /// method, as in `super.unmount()`.
4755 @mustCallSuper
4756 void unmount() {
4757 assert(_lifecycleState == _ElementLifecycle.inactive);
4758 assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
4759 assert(owner != null);
4760 assert(debugMaybeDispatchDisposed(this));
4761 // Use the private property to avoid a CastError during hot reload.
4762 final Key? key = _widget?.key;
4763 if (key is GlobalKey) {
4764 owner!._unregisterGlobalKey(key, this);
4765 }
4766 // Release resources to reduce the severity of memory leaks caused by
4767 // defunct, but accidentally retained Elements.
4768 _widget = null;
4769 _dependencies = null;
4770 _lifecycleState = _ElementLifecycle.defunct;
4771 }
4772
4773 /// Whether the child in the provided `slot` (or one of its descendants) must
4774 /// insert a [RenderObject] into its ancestor [RenderObjectElement] by calling
4775 /// [RenderObjectElement.insertRenderObjectChild] on it.
4776 ///
4777 /// This method is used to define non-rendering zones in the element tree (see
4778 /// [WidgetsBinding] for an explanation of rendering and non-rendering zones):
4779 ///
4780 /// Most branches of the [Element] tree are expected to eventually insert a
4781 /// [RenderObject] into their [RenderObjectElement] ancestor to construct the
4782 /// render tree. However, there is a notable exception: an [Element] may
4783 /// expect that the occupant of a certain child slot creates a new independent
4784 /// render tree and therefore is not allowed to insert a render object into
4785 /// the existing render tree. Those elements must return false from this
4786 /// method for the slot in question to signal to the child in that slot that
4787 /// it must not call [RenderObjectElement.insertRenderObjectChild] on its
4788 /// ancestor.
4789 ///
4790 /// As an example, the element backing the [ViewAnchor] returns false from
4791 /// this method for the [ViewAnchor.view] slot to enforce that it is occupied
4792 /// by e.g. a [View] widget, which will ultimately bootstrap a separate
4793 /// render tree for that view. Another example is the [ViewCollection] widget,
4794 /// which returns false for all its slots for the same reason.
4795 ///
4796 /// Overriding this method is not common, as elements behaving in the way
4797 /// described above are rare.
4798 bool debugExpectsRenderObjectForSlot(Object? slot) => true;
4799
4800 @override
4801 RenderObject? findRenderObject() {
4802 assert(() {
4803 if (_lifecycleState != _ElementLifecycle.active) {
4804 throw FlutterError.fromParts(<DiagnosticsNode>[
4805 ErrorSummary('Cannot get renderObject of inactive element.'),
4806 ErrorDescription(
4807 'In order for an element to have a valid renderObject, it must be '
4808 'active, which means it is part of the tree.\n'
4809 'Instead, this element is in the $_lifecycleState state.\n'
4810 'If you called this method from a State object, consider guarding '
4811 'it with State.mounted.',
4812 ),
4813 describeElement('The findRenderObject() method was called for the following element'),
4814 ]);
4815 }
4816 return true;
4817 }());
4818 return renderObject;
4819 }
4820
4821 @override
4822 Size? get size {
4823 assert(() {
4824 if (_lifecycleState != _ElementLifecycle.active) {
4825 // TODO(jacobr): is this a good separation into contract and violation?
4826 // I have added a line of white space.
4827 throw FlutterError.fromParts(<DiagnosticsNode>[
4828 ErrorSummary('Cannot get size of inactive element.'),
4829 ErrorDescription(
4830 'In order for an element to have a valid size, the element must be '
4831 'active, which means it is part of the tree.\n'
4832 'Instead, this element is in the $_lifecycleState state.',
4833 ),
4834 describeElement('The size getter was called for the following element'),
4835 ]);
4836 }
4837 if (owner!._debugBuilding) {
4838 throw FlutterError.fromParts(<DiagnosticsNode>[
4839 ErrorSummary('Cannot get size during build.'),
4840 ErrorDescription(
4841 'The size of this render object has not yet been determined because '
4842 'the framework is still in the process of building widgets, which '
4843 'means the render tree for this frame has not yet been determined. '
4844 'The size getter should only be called from paint callbacks or '
4845 'interaction event handlers (e.g. gesture callbacks).',
4846 ),
4847 ErrorSpacer(),
4848 ErrorHint(
4849 'If you need some sizing information during build to decide which '
4850 'widgets to build, consider using a LayoutBuilder widget, which can '
4851 'tell you the layout constraints at a given location in the tree. See '
4852 '<https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html> '
4853 'for more details.',
4854 ),
4855 ErrorSpacer(),
4856 describeElement('The size getter was called for the following element'),
4857 ]);
4858 }
4859 return true;
4860 }());
4861 final RenderObject? renderObject = findRenderObject();
4862 assert(() {
4863 if (renderObject == null) {
4864 throw FlutterError.fromParts(<DiagnosticsNode>[
4865 ErrorSummary('Cannot get size without a render object.'),
4866 ErrorHint(
4867 'In order for an element to have a valid size, the element must have '
4868 'an associated render object. This element does not have an associated '
4869 'render object, which typically means that the size getter was called '
4870 'too early in the pipeline (e.g., during the build phase) before the '
4871 'framework has created the render tree.',
4872 ),
4873 describeElement('The size getter was called for the following element'),
4874 ]);
4875 }
4876 if (renderObject is RenderSliver) {
4877 throw FlutterError.fromParts(<DiagnosticsNode>[
4878 ErrorSummary('Cannot get size from a RenderSliver.'),
4879 ErrorHint(
4880 'The render object associated with this element is a '
4881 '${renderObject.runtimeType}, which is a subtype of RenderSliver. '
4882 'Slivers do not have a size per se. They have a more elaborate '
4883 'geometry description, which can be accessed by calling '
4884 'findRenderObject and then using the "geometry" getter on the '
4885 'resulting object.',
4886 ),
4887 describeElement('The size getter was called for the following element'),
4888 renderObject.describeForError('The associated render sliver was'),
4889 ]);
4890 }
4891 if (renderObject is! RenderBox) {
4892 throw FlutterError.fromParts(<DiagnosticsNode>[
4893 ErrorSummary('Cannot get size from a render object that is not a RenderBox.'),
4894 ErrorHint(
4895 'Instead of being a subtype of RenderBox, the render object associated '
4896 'with this element is a ${renderObject.runtimeType}. If this type of '
4897 'render object does have a size, consider calling findRenderObject '
4898 'and extracting its size manually.',
4899 ),
4900 describeElement('The size getter was called for the following element'),
4901 renderObject.describeForError('The associated render object was'),
4902 ]);
4903 }
4904 final RenderBox box = renderObject;
4905 if (!box.hasSize) {
4906 throw FlutterError.fromParts(<DiagnosticsNode>[
4907 ErrorSummary('Cannot get size from a render object that has not been through layout.'),
4908 ErrorHint(
4909 'The size of this render object has not yet been determined because '
4910 'this render object has not yet been through layout, which typically '
4911 'means that the size getter was called too early in the pipeline '
4912 '(e.g., during the build phase) before the framework has determined '
4913 'the size and position of the render objects during layout.',
4914 ),
4915 describeElement('The size getter was called for the following element'),
4916 box.describeForError('The render object from which the size was to be obtained was'),
4917 ]);
4918 }
4919 if (box.debugNeedsLayout) {
4920 throw FlutterError.fromParts(<DiagnosticsNode>[
4921 ErrorSummary(
4922 'Cannot get size from a render object that has been marked dirty for layout.',
4923 ),
4924 ErrorHint(
4925 'The size of this render object is ambiguous because this render object has '
4926 'been modified since it was last laid out, which typically means that the size '
4927 'getter was called too early in the pipeline (e.g., during the build phase) '
4928 'before the framework has determined the size and position of the render '
4929 'objects during layout.',
4930 ),
4931 describeElement('The size getter was called for the following element'),
4932 box.describeForError('The render object from which the size was to be obtained was'),
4933 ErrorHint(
4934 'Consider using debugPrintMarkNeedsLayoutStacks to determine why the render '
4935 'object in question is dirty, if you did not expect this.',
4936 ),
4937 ]);
4938 }
4939 return true;
4940 }());
4941 if (renderObject is RenderBox) {
4942 return renderObject.size;
4943 }
4944 return null;
4945 }
4946
4947 PersistentHashMap<Type, InheritedElement>? _inheritedElements;
4948 Set<InheritedElement>? _dependencies;
4949 bool _hadUnsatisfiedDependencies = false;
4950
4951 bool _debugCheckStateIsActiveForAncestorLookup() {
4952 assert(() {
4953 if (_lifecycleState != _ElementLifecycle.active) {
4954 throw FlutterError.fromParts(<DiagnosticsNode>[
4955 ErrorSummary("Looking up a deactivated widget's ancestor is unsafe."),
4956 ErrorDescription(
4957 "At this point the state of the widget's element tree is no longer "
4958 'stable.',
4959 ),
4960 ErrorHint(
4961 "To safely refer to a widget's ancestor in its dispose() method, "
4962 'save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() '
4963 "in the widget's didChangeDependencies() method.",
4964 ),
4965 ]);
4966 }
4967 return true;
4968 }());
4969 return true;
4970 }
4971
4972 /// Returns `true` if [dependOnInheritedElement] was previously called with [ancestor].
4973 @protected
4974 bool doesDependOnInheritedElement(InheritedElement ancestor) {
4975 return _dependencies?.contains(ancestor) ?? false;
4976 }
4977
4978 @override
4979 InheritedWidget dependOnInheritedElement(InheritedElement ancestor, {Object? aspect}) {
4980 _dependencies ??= HashSet<InheritedElement>();
4981 _dependencies!.add(ancestor);
4982 ancestor.updateDependencies(this, aspect);
4983 return ancestor.widget as InheritedWidget;
4984 }
4985
4986 @override
4987 T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
4988 assert(_debugCheckStateIsActiveForAncestorLookup());
4989 final InheritedElement? ancestor = _inheritedElements?[T];
4990 if (ancestor != null) {
4991 return dependOnInheritedElement(ancestor, aspect: aspect) as T;
4992 }
4993 _hadUnsatisfiedDependencies = true;
4994 return null;
4995 }
4996
4997 @override
4998 T? getInheritedWidgetOfExactType<T extends InheritedWidget>() {
4999 return getElementForInheritedWidgetOfExactType<T>()?.widget as T?;
5000 }
5001
5002 @override
5003 InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
5004 assert(_debugCheckStateIsActiveForAncestorLookup());
5005 return _inheritedElements?[T];
5006 }
5007
5008 /// Called in [Element.mount] and [Element.activate] to register this element in
5009 /// the notification tree.
5010 ///
5011 /// This method is only exposed so that [NotifiableElementMixin] can be implemented.
5012 /// Subclasses of [Element] that wish to respond to notifications should mix that
5013 /// in instead.
5014 ///
5015 /// See also:
5016 /// * [NotificationListener], a widget that allows listening to notifications.
5017 @protected
5018 void attachNotificationTree() {
5019 _notificationTree = _parent?._notificationTree;
5020 }
5021
5022 void _updateInheritance() {
5023 assert(_lifecycleState == _ElementLifecycle.active);
5024 _inheritedElements = _parent?._inheritedElements;
5025 }
5026
5027 @override
5028 T? findAncestorWidgetOfExactType<T extends Widget>() {
5029 assert(_debugCheckStateIsActiveForAncestorLookup());
5030 Element? ancestor = _parent;
5031 while (ancestor != null && ancestor.widget.runtimeType != T) {
5032 ancestor = ancestor._parent;
5033 }
5034 return ancestor?.widget as T?;
5035 }
5036
5037 @override
5038 T? findAncestorStateOfType<T extends State<StatefulWidget>>() {
5039 assert(_debugCheckStateIsActiveForAncestorLookup());
5040 Element? ancestor = _parent;
5041 while (ancestor != null) {
5042 if (ancestor is StatefulElement && ancestor.state is T) {
5043 break;
5044 }
5045 ancestor = ancestor._parent;
5046 }
5047 final StatefulElement? statefulAncestor = ancestor as StatefulElement?;
5048 return statefulAncestor?.state as T?;
5049 }
5050
5051 @override
5052 T? findRootAncestorStateOfType<T extends State<StatefulWidget>>() {
5053 assert(_debugCheckStateIsActiveForAncestorLookup());
5054 Element? ancestor = _parent;
5055 StatefulElement? statefulAncestor;
5056 while (ancestor != null) {
5057 if (ancestor is StatefulElement && ancestor.state is T) {
5058 statefulAncestor = ancestor;
5059 }
5060 ancestor = ancestor._parent;
5061 }
5062 return statefulAncestor?.state as T?;
5063 }
5064
5065 @override
5066 T? findAncestorRenderObjectOfType<T extends RenderObject>() {
5067 assert(_debugCheckStateIsActiveForAncestorLookup());
5068 Element? ancestor = _parent;
5069 while (ancestor != null) {
5070 if (ancestor is RenderObjectElement && ancestor.renderObject is T) {
5071 return ancestor.renderObject as T;
5072 }
5073 ancestor = ancestor._parent;
5074 }
5075 return null;
5076 }
5077
5078 @override
5079 void visitAncestorElements(ConditionalElementVisitor visitor) {
5080 assert(_debugCheckStateIsActiveForAncestorLookup());
5081 Element? ancestor = _parent;
5082 while (ancestor != null && visitor(ancestor)) {
5083 ancestor = ancestor._parent;
5084 }
5085 }
5086
5087 /// Called when a dependency of this element changes.
5088 ///
5089 /// The [dependOnInheritedWidgetOfExactType] registers this element as depending on
5090 /// inherited information of the given type. When the information of that type
5091 /// changes at this location in the tree (e.g., because the [InheritedElement]
5092 /// updated to a new [InheritedWidget] and
5093 /// [InheritedWidget.updateShouldNotify] returned true), the framework calls
5094 /// this function to notify this element of the change.
5095 @mustCallSuper
5096 void didChangeDependencies() {
5097 assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
5098 assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
5099 markNeedsBuild();
5100 }
5101
5102 bool _debugCheckOwnerBuildTargetExists(String methodName) {
5103 assert(() {
5104 if (owner!._debugCurrentBuildTarget == null) {
5105 throw FlutterError.fromParts(<DiagnosticsNode>[
5106 ErrorSummary(
5107 '$methodName for ${widget.runtimeType} was called at an '
5108 'inappropriate time.',
5109 ),
5110 ErrorDescription('It may only be called while the widgets are being built.'),
5111 ErrorHint(
5112 'A possible cause of this error is when $methodName is called during '
5113 'one of:\n'
5114 ' * network I/O event\n'
5115 ' * file I/O event\n'
5116 ' * timer\n'
5117 ' * microtask (caused by Future.then, async/await, scheduleMicrotask)',
5118 ),
5119 ]);
5120 }
5121 return true;
5122 }());
5123 return true;
5124 }
5125
5126 /// Returns a description of what caused this element to be created.
5127 ///
5128 /// Useful for debugging the source of an element.
5129 String debugGetCreatorChain(int limit) {
5130 final List<String> chain = <String>[];
5131 Element? node = this;
5132 while (chain.length < limit && node != null) {
5133 chain.add(node.toStringShort());
5134 node = node._parent;
5135 }
5136 if (node != null) {
5137 chain.add('\u22EF');
5138 }
5139 return chain.join(' \u2190 ');
5140 }
5141
5142 /// Returns the parent chain from this element back to the root of the tree.
5143 ///
5144 /// Useful for debug display of a tree of Elements with only nodes in the path
5145 /// from the root to this Element expanded.
5146 List<Element> debugGetDiagnosticChain() {
5147 final List<Element> chain = <Element>[this];
5148 Element? node = _parent;
5149 while (node != null) {
5150 chain.add(node);
5151 node = node._parent;
5152 }
5153 return chain;
5154 }
5155
5156 @override
5157 void dispatchNotification(Notification notification) {
5158 _notificationTree?.dispatchNotification(notification);
5159 }
5160
5161 /// A short, textual description of this element.
5162 @override
5163 String toStringShort() => _widget?.toStringShort() ?? '${describeIdentity(this)}(DEFUNCT)';
5164
5165 @override
5166 DiagnosticsNode toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) {
5167 return _ElementDiagnosticableTreeNode(name: name, value: this, style: style);
5168 }
5169
5170 @override
5171 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
5172 super.debugFillProperties(properties);
5173 properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
5174 if (_lifecycleState != _ElementLifecycle.initial) {
5175 properties.add(ObjectFlagProperty<int>('depth', depth, ifNull: 'no depth'));
5176 }
5177 properties.add(ObjectFlagProperty<Widget>('widget', _widget, ifNull: 'no widget'));
5178 properties.add(
5179 DiagnosticsProperty<Key>(
5180 'key',
5181 _widget?.key,
5182 showName: false,
5183 defaultValue: null,
5184 level: DiagnosticLevel.hidden,
5185 ),
5186 );
5187 _widget?.debugFillProperties(properties);
5188 properties.add(FlagProperty('dirty', value: dirty, ifTrue: 'dirty'));
5189 final Set<InheritedElement>? deps = _dependencies;
5190 if (deps != null && deps.isNotEmpty) {
5191 final List<InheritedElement> sortedDependencies = deps.toList()
5192 ..sort(
5193 (InheritedElement a, InheritedElement b) =>
5194 a.toStringShort().compareTo(b.toStringShort()),
5195 );
5196 final List<DiagnosticsNode> diagnosticsDependencies = sortedDependencies
5197 .map(
5198 (InheritedElement element) =>
5199 element.widget.toDiagnosticsNode(style: DiagnosticsTreeStyle.sparse),
5200 )
5201 .toList();
5202 properties.add(
5203 DiagnosticsProperty<Set<InheritedElement>>(
5204 'dependencies',
5205 deps,
5206 description: diagnosticsDependencies.toString(),
5207 ),
5208 );
5209 }
5210 }
5211
5212 @override
5213 List<DiagnosticsNode> debugDescribeChildren() {
5214 final List<DiagnosticsNode> children = <DiagnosticsNode>[];
5215 visitChildren((Element child) {
5216 children.add(child.toDiagnosticsNode());
5217 });
5218 return children;
5219 }
5220
5221 /// Returns true if the element has been marked as needing rebuilding.
5222 ///
5223 /// The flag is true when the element is first created and after
5224 /// [markNeedsBuild] has been called. The flag is typically reset to false in
5225 /// the [performRebuild] implementation, but certain elements (that of the
5226 /// [LayoutBuilder] widget, for example) may choose to override [markNeedsBuild]
5227 /// such that it does not set the [dirty] flag to `true` when called.
5228 bool get dirty => _dirty;
5229 bool _dirty = true;
5230
5231 // Whether this is in _buildScope._dirtyElements. This is used to know whether
5232 // we should be adding the element back into the list when it's reactivated.
5233 bool _inDirtyList = false;
5234
5235 // Whether we've already built or not. Set in [rebuild].
5236 bool _debugBuiltOnce = false;
5237
5238 /// Marks the element as dirty and adds it to the global list of widgets to
5239 /// rebuild in the next frame.
5240 ///
5241 /// Since it is inefficient to build an element twice in one frame,
5242 /// applications and widgets should be structured so as to only mark
5243 /// widgets dirty during event handlers before the frame begins, not during
5244 /// the build itself.
5245 void markNeedsBuild() {
5246 assert(_lifecycleState != _ElementLifecycle.defunct);
5247 if (_lifecycleState != _ElementLifecycle.active) {
5248 return;
5249 }
5250 assert(owner != null);
5251 assert(_lifecycleState == _ElementLifecycle.active);
5252 assert(() {
5253 if (owner!._debugBuilding) {
5254 assert(owner!._debugCurrentBuildTarget != null);
5255 assert(owner!._debugStateLocked);
5256 if (_debugIsDescendantOf(owner!._debugCurrentBuildTarget!)) {
5257 return true;
5258 }
5259 final List<DiagnosticsNode> information = <DiagnosticsNode>[
5260 ErrorSummary('setState() or markNeedsBuild() called during build.'),
5261 ErrorDescription(
5262 'This ${widget.runtimeType} widget cannot be marked as needing to build because the framework '
5263 'is already in the process of building widgets. A widget can be marked as '
5264 'needing to be built during the build phase only if one of its ancestors '
5265 'is currently building. This exception is allowed because the framework '
5266 'builds parent widgets before children, which means a dirty descendant '
5267 'will always be built. Otherwise, the framework might not visit this '
5268 'widget during this build phase.',
5269 ),
5270 describeElement('The widget on which setState() or markNeedsBuild() was called was'),
5271 ];
5272 if (owner!._debugCurrentBuildTarget != null) {
5273 information.add(
5274 owner!._debugCurrentBuildTarget!.describeWidget(
5275 'The widget which was currently being built when the offending call was made was',
5276 ),
5277 );
5278 }
5279 throw FlutterError.fromParts(information);
5280 } else if (owner!._debugStateLocked) {
5281 throw FlutterError.fromParts(<DiagnosticsNode>[
5282 ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),
5283 ErrorDescription(
5284 'This ${widget.runtimeType} widget cannot be marked as needing to build '
5285 'because the framework is locked.',
5286 ),
5287 describeElement('The widget on which setState() or markNeedsBuild() was called was'),
5288 ]);
5289 }
5290 return true;
5291 }());
5292 if (dirty) {
5293 return;
5294 }
5295 _dirty = true;
5296 owner!.scheduleBuildFor(this);
5297 }
5298
5299 /// Cause the widget to update itself. In debug builds, also verify various
5300 /// invariants.
5301 ///
5302 /// Called by the [BuildOwner] when [BuildOwner.scheduleBuildFor] has been
5303 /// called to mark this element dirty, by [mount] when the element is first
5304 /// built, and by [update] when the widget has changed.
5305 ///
5306 /// The method will only rebuild if [dirty] is true. To rebuild regardless
5307 /// of the [dirty] flag, set `force` to true. Forcing a rebuild is convenient
5308 /// from [update], during which [dirty] is false.
5309 ///
5310 /// ## When rebuilds happen
5311 ///
5312 /// ### Terminology
5313 ///
5314 /// [Widget]s represent the configuration of [Element]s. Each [Element] has a
5315 /// widget, specified in [Element.widget]. The term "widget" is often used
5316 /// when strictly speaking "element" would be more correct.
5317 ///
5318 /// While an [Element] has a current [Widget], over time, that widget may be
5319 /// replaced by others. For example, the element backing a [ColoredBox] may
5320 /// first have as its widget a [ColoredBox] whose [ColoredBox.color] is blue,
5321 /// then later be given a new [ColoredBox] whose color is green.
5322 ///
5323 /// At any particular time, multiple [Element]s in the same tree may have the
5324 /// same [Widget]. For example, the same [ColoredBox] with the green color may
5325 /// be used in multiple places in the widget tree at the same time, each being
5326 /// backed by a different [Element].
5327 ///
5328 /// ### Marking an element dirty
5329 ///
5330 /// An [Element] can be marked dirty between frames. This can happen for various
5331 /// reasons, including the following:
5332 ///
5333 /// * The [State] of a [StatefulWidget] can cause its [Element] to be marked
5334 /// dirty by calling the [State.setState] method.
5335 ///
5336 /// * When an [InheritedWidget] changes, descendants that have previously
5337 /// subscribed to it will be marked dirty.
5338 ///
5339 /// * During a hot reload, every element is marked dirty (using [Element.reassemble]).
5340 ///
5341 /// ### Rebuilding
5342 ///
5343 /// Dirty elements are rebuilt during the next frame. Precisely how this is
5344 /// done depends on the kind of element. A [StatelessElement] rebuilds by
5345 /// using its widget's [StatelessWidget.build] method. A [StatefulElement]
5346 /// rebuilds by using its widget's state's [State.build] method. A
5347 /// [RenderObjectElement] rebuilds by updating its [RenderObject].
5348 ///
5349 /// In many cases, the end result of rebuilding is a single child widget
5350 /// or (for [MultiChildRenderObjectElement]s) a list of children widgets.
5351 ///
5352 /// These child widgets are used to update the [widget] property of the
5353 /// element's child (or children) elements. The new [Widget] is considered to
5354 /// correspond to an existing [Element] if it has the same [Type] and [Key].
5355 /// (In the case of [MultiChildRenderObjectElement]s, some effort is put into
5356 /// tracking widgets even when they change order; see
5357 /// [RenderObjectElement.updateChildren].)
5358 ///
5359 /// If there was no corresponding previous child, this results in a new
5360 /// [Element] being created (using [Widget.createElement]); that element is
5361 /// then itself built, recursively.
5362 ///
5363 /// If there was a child previously but the build did not provide a
5364 /// corresponding child to update it, then the old child is discarded (or, in
5365 /// cases involving [GlobalKey] reparenting, reused elsewhere in the element
5366 /// tree).
5367 ///
5368 /// The most common case, however, is that there was a corresponding previous
5369 /// child. This is handled by asking the child [Element] to update itself
5370 /// using the new child [Widget]. In the case of [StatefulElement]s, this
5371 /// is what triggers [State.didUpdateWidget].
5372 ///
5373 /// ### Not rebuilding
5374 ///
5375 /// Before an [Element] is told to update itself with a new [Widget], the old
5376 /// and new objects are compared using `operator ==`.
5377 ///
5378 /// In general, this is equivalent to doing a comparison using [identical] to
5379 /// see if the two objects are in fact the exact same instance. If they are,
5380 /// and if the element is not already marked dirty for other reasons, then the
5381 /// element skips updating itself as it can determine with certainty that
5382 /// there would be no value in updating itself or its descendants.
5383 ///
5384 /// It is strongly advised to avoid overriding `operator ==` on [Widget]
5385 /// objects. While doing so seems like it could improve performance, in
5386 /// practice, for non-leaf widgets, it results in O(N²) behavior. This is
5387 /// because by necessity the comparison would have to include comparing child
5388 /// widgets, and if those child widgets also implement `operator ==`, it
5389 /// ultimately results in a complete walk of the widget tree... which is then
5390 /// repeated at each level of the tree. In practice, just rebuilding is
5391 /// cheaper. (Additionally, if _any_ subclass of [Widget] used in an
5392 /// application implements `operator ==`, then the compiler cannot inline the
5393 /// comparison anywhere, because it has to treat the call as virtual just in
5394 /// case the instance happens to be one that has an overridden operator.)
5395 ///
5396 /// Instead, the best way to avoid unnecessary rebuilds is to cache the
5397 /// widgets that are returned from [State.build], so that each frame the same
5398 /// widgets are used until such time as they change. Several mechanisms exist
5399 /// to encourage this: `const` widgets, for example, are a form of automatic
5400 /// caching (if a widget is constructed using the `const` keyword, the same
5401 /// instance is returned each time it is constructed with the same arguments).
5402 ///
5403 /// Another example is the [AnimatedBuilder.child] property, which allows the
5404 /// non-animating parts of a subtree to remain static even as the
5405 /// [AnimatedBuilder.builder] callback recreates the other components.
5406 @pragma('dart2js:tryInline')
5407 @pragma('vm:prefer-inline')
5408 @pragma('wasm:prefer-inline')
5409 void rebuild({bool force = false}) {
5410 assert(_lifecycleState != _ElementLifecycle.initial);
5411 if (_lifecycleState != _ElementLifecycle.active || (!_dirty && !force)) {
5412 return;
5413 }
5414 assert(() {
5415 debugOnRebuildDirtyWidget?.call(this, _debugBuiltOnce);
5416 if (debugPrintRebuildDirtyWidgets) {
5417 if (!_debugBuiltOnce) {
5418 debugPrint('Building $this');
5419 _debugBuiltOnce = true;
5420 } else {
5421 debugPrint('Rebuilding $this');
5422 }
5423 }
5424 return true;
5425 }());
5426 assert(_lifecycleState == _ElementLifecycle.active);
5427 assert(owner!._debugStateLocked);
5428 Element? debugPreviousBuildTarget;
5429 assert(() {
5430 debugPreviousBuildTarget = owner!._debugCurrentBuildTarget;
5431 owner!._debugCurrentBuildTarget = this;
5432 return true;
5433 }());
5434 try {
5435 performRebuild();
5436 } finally {
5437 assert(() {
5438 owner!._debugElementWasRebuilt(this);
5439 assert(owner!._debugCurrentBuildTarget == this);
5440 owner!._debugCurrentBuildTarget = debugPreviousBuildTarget;
5441 return true;
5442 }());
5443 }
5444 assert(!_dirty);
5445 }
5446
5447 /// Cause the widget to update itself.
5448 ///
5449 /// Called by [rebuild] after the appropriate checks have been made.
5450 ///
5451 /// The base implementation only clears the [dirty] flag.
5452 @protected
5453 @mustCallSuper
5454 void performRebuild() {
5455 _dirty = false;
5456 }
5457}
5458
5459class _ElementDiagnosticableTreeNode extends DiagnosticableTreeNode {
5460 _ElementDiagnosticableTreeNode({
5461 super.name,
5462 required Element super.value,
5463 required super.style,
5464 this.stateful = false,
5465 });
5466
5467 final bool stateful;
5468
5469 @override
5470 Map<String, Object?> toJsonMap(DiagnosticsSerializationDelegate delegate) {
5471 final Map<String, Object?> json = super.toJsonMap(delegate);
5472 final Element element = value as Element;
5473 if (!element.debugIsDefunct) {
5474 json['widgetRuntimeType'] = element.widget.runtimeType.toString();
5475 }
5476 json['stateful'] = stateful;
5477 return json;
5478 }
5479}
5480
5481/// Signature for the constructor that is called when an error occurs while
5482/// building a widget.
5483///
5484/// The argument provides information regarding the cause of the error.
5485///
5486/// See also:
5487///
5488/// * [ErrorWidget.builder], which can be set to override the default
5489/// [ErrorWidget] builder.
5490/// * [FlutterError.reportError], which is typically called with the same
5491/// [FlutterErrorDetails] object immediately prior to [ErrorWidget.builder]
5492/// being called.
5493typedef ErrorWidgetBuilder = Widget Function(FlutterErrorDetails details);
5494
5495/// A widget that renders an exception's message.
5496///
5497/// This widget is used when a build method fails, to help with determining
5498/// where the problem lies. Exceptions are also logged to the console, which you
5499/// can read using `flutter logs`. The console will also include additional
5500/// information such as the stack trace for the exception.
5501///
5502/// It is possible to override this widget.
5503///
5504/// {@tool dartpad}
5505/// This example shows how to override the standard error widget builder in release
5506/// mode, but use the standard one in debug mode.
5507///
5508/// The error occurs when you click the "Error Prone" button.
5509///
5510/// ** See code in examples/api/lib/widgets/framework/error_widget.0.dart **
5511/// {@end-tool}
5512///
5513/// See also:
5514///
5515/// * [FlutterError.onError], which can be set to a method that exits the
5516/// application if that is preferable to showing an error message.
5517/// * <https://docs.flutter.dev/testing/errors>, more information about error
5518/// handling in Flutter.
5519class ErrorWidget extends LeafRenderObjectWidget {
5520 /// Creates a widget that displays the given exception.
5521 ///
5522 /// The message will be the stringification of the given exception, unless
5523 /// computing that value itself throws an exception, in which case it will
5524 /// be the string "Error".
5525 ///
5526 /// If this object is inspected from an IDE or the devtools, and the original
5527 /// exception is a [FlutterError] object, the original exception itself will
5528 /// be shown in the inspection output.
5529 ErrorWidget(Object exception)
5530 : message = _stringify(exception),
5531 _flutterError = exception is FlutterError ? exception : null,
5532 super(key: UniqueKey());
5533
5534 /// Creates a widget that displays the given error message.
5535 ///
5536 /// An explicit [FlutterError] can be provided to be reported to inspection
5537 /// tools. It need not match the message.
5538 ErrorWidget.withDetails({this.message = '', FlutterError? error})
5539 : _flutterError = error,
5540 super(key: UniqueKey());
5541
5542 /// The configurable factory for [ErrorWidget].
5543 ///
5544 /// When an error occurs while building a widget, the broken widget is
5545 /// replaced by the widget returned by this function. By default, an
5546 /// [ErrorWidget] is returned.
5547 ///
5548 /// The system is typically in an unstable state when this function is called.
5549 /// An exception has just been thrown in the middle of build (and possibly
5550 /// layout), so surrounding widgets and render objects may be in a rather
5551 /// fragile state. The framework itself (especially the [BuildOwner]) may also
5552 /// be confused, and additional exceptions are quite likely to be thrown.
5553 ///
5554 /// Because of this, it is highly recommended that the widget returned from
5555 /// this function perform the least amount of work possible. A
5556 /// [LeafRenderObjectWidget] is the best choice, especially one that
5557 /// corresponds to a [RenderBox] that can handle the most absurd of incoming
5558 /// constraints. The default constructor maps to a [RenderErrorBox].
5559 ///
5560 /// The default behavior is to show the exception's message in debug mode,
5561 /// and to show nothing but a gray background in release builds.
5562 ///
5563 /// See also:
5564 ///
5565 /// * [FlutterError.onError], which is typically called with the same
5566 /// [FlutterErrorDetails] object immediately prior to this callback being
5567 /// invoked, and which can also be configured to control how errors are
5568 /// reported.
5569 /// * <https://docs.flutter.dev/testing/errors>, more information about error
5570 /// handling in Flutter.
5571 static ErrorWidgetBuilder builder = _defaultErrorWidgetBuilder;
5572
5573 static Widget _defaultErrorWidgetBuilder(FlutterErrorDetails details) {
5574 String message = '';
5575 assert(() {
5576 message =
5577 '${_stringify(details.exception)}\nSee also: https://docs.flutter.dev/testing/errors';
5578 return true;
5579 }());
5580 final Object exception = details.exception;
5581 return ErrorWidget.withDetails(
5582 message: message,
5583 error: exception is FlutterError ? exception : null,
5584 );
5585 }
5586
5587 static String _stringify(Object? exception) {
5588 try {
5589 return exception.toString();
5590 } catch (error) {
5591 // If we get here, it means things have really gone off the rails, and we're better
5592 // off just returning a simple string and letting the developer find out what the
5593 // root cause of all their problems are by looking at the console logs.
5594 }
5595 return 'Error';
5596 }
5597
5598 /// The message to display.
5599 final String message;
5600 final FlutterError? _flutterError;
5601
5602 @override
5603 RenderBox createRenderObject(BuildContext context) => RenderErrorBox(message);
5604
5605 @override
5606 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
5607 super.debugFillProperties(properties);
5608 if (_flutterError == null) {
5609 properties.add(StringProperty('message', message, quoted: false));
5610 } else {
5611 properties.add(_flutterError.toDiagnosticsNode(style: DiagnosticsTreeStyle.whitespace));
5612 }
5613 }
5614}
5615
5616/// Signature for a function that creates a widget, e.g. [StatelessWidget.build]
5617/// or [State.build].
5618///
5619/// Used by [Builder.builder], [OverlayEntry.builder], etc.
5620///
5621/// See also:
5622///
5623/// * [IndexedWidgetBuilder], which is similar but also takes an index.
5624/// * [TransitionBuilder], which is similar but also takes a child.
5625/// * [ValueWidgetBuilder], which is similar but takes a value and a child.
5626typedef WidgetBuilder = Widget Function(BuildContext context);
5627
5628/// Signature for a function that creates a widget for a given index, e.g., in a
5629/// list.
5630///
5631/// Used by [ListView.builder] and other APIs that use lazily-generated widgets.
5632///
5633/// See also:
5634///
5635/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5636/// * [TransitionBuilder], which is similar but also takes a child.
5637/// * [NullableIndexedWidgetBuilder], which is similar but may return null.
5638typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
5639
5640/// Signature for a function that creates a widget for a given index, e.g., in a
5641/// list, but may return null.
5642///
5643/// Used by [SliverChildBuilderDelegate.builder] and other APIs that
5644/// use lazily-generated widgets where the child count is not known
5645/// ahead of time.
5646///
5647/// Unlike most builders, this callback can return null, indicating the index
5648/// is out of range. Whether and when this is valid depends on the semantics
5649/// of the builder. For example, [SliverChildBuilderDelegate.builder] returns
5650/// null when the index is out of range, where the range is defined by the
5651/// [SliverChildBuilderDelegate.childCount]; so in that case the `index`
5652/// parameter's value may determine whether returning null is valid or not.
5653///
5654/// See also:
5655///
5656/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5657/// * [TransitionBuilder], which is similar but also takes a child.
5658/// * [IndexedWidgetBuilder], which is similar but not nullable.
5659typedef NullableIndexedWidgetBuilder = Widget? Function(BuildContext context, int index);
5660
5661/// A builder that builds a widget given a child.
5662///
5663/// The child should typically be part of the returned widget tree.
5664///
5665/// Used by [AnimatedBuilder.builder], [ListenableBuilder.builder],
5666/// [WidgetsApp.builder], and [MaterialApp.builder].
5667///
5668/// See also:
5669///
5670/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5671/// * [IndexedWidgetBuilder], which is similar but also takes an index.
5672/// * [ValueWidgetBuilder], which is similar but takes a value and a child.
5673typedef TransitionBuilder = Widget Function(BuildContext context, Widget? child);
5674
5675/// An [Element] that composes other [Element]s.
5676///
5677/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
5678/// [RenderObject]s indirectly by creating other [Element]s.
5679///
5680/// Contrast with [RenderObjectElement].
5681abstract class ComponentElement extends Element {
5682 /// Creates an element that uses the given widget as its configuration.
5683 ComponentElement(super.widget);
5684
5685 Element? _child;
5686
5687 bool _debugDoingBuild = false;
5688 @override
5689 bool get debugDoingBuild => _debugDoingBuild;
5690
5691 @override
5692 Element? get renderObjectAttachingChild => _child;
5693
5694 @override
5695 void mount(Element? parent, Object? newSlot) {
5696 super.mount(parent, newSlot);
5697 assert(_child == null);
5698 assert(_lifecycleState == _ElementLifecycle.active);
5699 _firstBuild();
5700 assert(_child != null);
5701 }
5702
5703 void _firstBuild() {
5704 // StatefulElement overrides this to also call state.didChangeDependencies.
5705 rebuild(); // This eventually calls performRebuild.
5706 }
5707
5708 /// Calls the [StatelessWidget.build] method of the [StatelessWidget] object
5709 /// (for stateless widgets) or the [State.build] method of the [State] object
5710 /// (for stateful widgets) and then updates the widget tree.
5711 ///
5712 /// Called automatically during [mount] to generate the first build, and by
5713 /// [rebuild] when the element needs updating.
5714 @override
5715 @pragma('vm:notify-debugger-on-exception')
5716 void performRebuild() {
5717 Widget? built;
5718 try {
5719 assert(() {
5720 _debugDoingBuild = true;
5721 return true;
5722 }());
5723 built = build();
5724 assert(() {
5725 _debugDoingBuild = false;
5726 return true;
5727 }());
5728 debugWidgetBuilderValue(widget, built);
5729 } catch (e, stack) {
5730 _debugDoingBuild = false;
5731 built = ErrorWidget.builder(
5732 _reportException(
5733 ErrorDescription('building $this'),
5734 e,
5735 stack,
5736 informationCollector: () => <DiagnosticsNode>[
5737 if (kDebugMode) DiagnosticsDebugCreator(DebugCreator(this)),
5738 ],
5739 ),
5740 );
5741 } finally {
5742 // We delay marking the element as clean until after calling build() so
5743 // that attempts to markNeedsBuild() during build() will be ignored.
5744 super.performRebuild(); // clears the "dirty" flag
5745 }
5746 try {
5747 _child = updateChild(_child, built, slot);
5748 assert(_child != null);
5749 } catch (e, stack) {
5750 built = ErrorWidget.builder(
5751 _reportException(
5752 ErrorDescription('building $this'),
5753 e,
5754 stack,
5755 informationCollector: () => <DiagnosticsNode>[
5756 if (kDebugMode) DiagnosticsDebugCreator(DebugCreator(this)),
5757 ],
5758 ),
5759 );
5760 _child = updateChild(null, built, slot);
5761 }
5762 }
5763
5764 /// Subclasses should override this function to actually call the appropriate
5765 /// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
5766 /// their widget.
5767 @protected
5768 Widget build();
5769
5770 @override
5771 void visitChildren(ElementVisitor visitor) {
5772 if (_child != null) {
5773 visitor(_child!);
5774 }
5775 }
5776
5777 @override
5778 void forgetChild(Element child) {
5779 assert(child == _child);
5780 _child = null;
5781 super.forgetChild(child);
5782 }
5783}
5784
5785/// An [Element] that uses a [StatelessWidget] as its configuration.
5786class StatelessElement extends ComponentElement {
5787 /// Creates an element that uses the given widget as its configuration.
5788 StatelessElement(StatelessWidget super.widget);
5789
5790 @override
5791 Widget build() => (widget as StatelessWidget).build(this);
5792
5793 @override
5794 void update(StatelessWidget newWidget) {
5795 super.update(newWidget);
5796 assert(widget == newWidget);
5797 rebuild(force: true);
5798 }
5799}
5800
5801/// An [Element] that uses a [StatefulWidget] as its configuration.
5802class StatefulElement extends ComponentElement {
5803 /// Creates an element that uses the given widget as its configuration.
5804 StatefulElement(StatefulWidget widget) : _state = widget.createState(), super(widget) {
5805 assert(() {
5806 if (!state._debugTypesAreRight(widget)) {
5807 throw FlutterError.fromParts(<DiagnosticsNode>[
5808 ErrorSummary(
5809 'StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>',
5810 ),
5811 ErrorDescription(
5812 'The createState function for ${widget.runtimeType} returned a state '
5813 'of type ${state.runtimeType}, which is not a subtype of '
5814 'State<${widget.runtimeType}>, violating the contract for createState.',
5815 ),
5816 ]);
5817 }
5818 return true;
5819 }());
5820 assert(state._element == null);
5821 state._element = this;
5822 assert(
5823 state._widget == null,
5824 'The createState function for $widget returned an old or invalid state '
5825 'instance: ${state._widget}, which is not null, violating the contract '
5826 'for createState.',
5827 );
5828 state._widget = widget;
5829 assert(state._debugLifecycleState == _StateLifecycle.created);
5830 }
5831
5832 @override
5833 Widget build() => state.build(this);
5834
5835 /// The [State] instance associated with this location in the tree.
5836 ///
5837 /// There is a one-to-one relationship between [State] objects and the
5838 /// [StatefulElement] objects that hold them. The [State] objects are created
5839 /// by [StatefulElement] in [mount].
5840 State<StatefulWidget> get state => _state!;
5841 State<StatefulWidget>? _state;
5842
5843 @override
5844 void reassemble() {
5845 state.reassemble();
5846 super.reassemble();
5847 }
5848
5849 @override
5850 void _firstBuild() {
5851 assert(state._debugLifecycleState == _StateLifecycle.created);
5852 final Object? debugCheckForReturnedFuture = state.initState() as dynamic;
5853 assert(() {
5854 if (debugCheckForReturnedFuture is Future) {
5855 throw FlutterError.fromParts(<DiagnosticsNode>[
5856 ErrorSummary('${state.runtimeType}.initState() returned a Future.'),
5857 ErrorDescription('State.initState() must be a void method without an `async` keyword.'),
5858 ErrorHint(
5859 'Rather than awaiting on asynchronous work directly inside of initState, '
5860 'call a separate method to do this work without awaiting it.',
5861 ),
5862 ]);
5863 }
5864 return true;
5865 }());
5866 assert(() {
5867 state._debugLifecycleState = _StateLifecycle.initialized;
5868 return true;
5869 }());
5870 state.didChangeDependencies();
5871 assert(() {
5872 state._debugLifecycleState = _StateLifecycle.ready;
5873 return true;
5874 }());
5875 super._firstBuild();
5876 }
5877
5878 @override
5879 void performRebuild() {
5880 if (_didChangeDependencies) {
5881 state.didChangeDependencies();
5882 _didChangeDependencies = false;
5883 }
5884 super.performRebuild();
5885 }
5886
5887 @override
5888 void update(StatefulWidget newWidget) {
5889 super.update(newWidget);
5890 assert(widget == newWidget);
5891 final StatefulWidget oldWidget = state._widget!;
5892 state._widget = widget as StatefulWidget;
5893 final Object? debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic;
5894 assert(() {
5895 if (debugCheckForReturnedFuture is Future) {
5896 throw FlutterError.fromParts(<DiagnosticsNode>[
5897 ErrorSummary('${state.runtimeType}.didUpdateWidget() returned a Future.'),
5898 ErrorDescription(
5899 'State.didUpdateWidget() must be a void method without an `async` keyword.',
5900 ),
5901 ErrorHint(
5902 'Rather than awaiting on asynchronous work directly inside of didUpdateWidget, '
5903 'call a separate method to do this work without awaiting it.',
5904 ),
5905 ]);
5906 }
5907 return true;
5908 }());
5909 rebuild(force: true);
5910 }
5911
5912 @override
5913 void activate() {
5914 super.activate();
5915 state.activate();
5916 // Since the State could have observed the deactivate() and thus disposed of
5917 // resources allocated in the build method, we have to rebuild the widget
5918 // so that its State can reallocate its resources.
5919 assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
5920 markNeedsBuild();
5921 }
5922
5923 @override
5924 void deactivate() {
5925 state.deactivate();
5926 super.deactivate();
5927 }
5928
5929 @override
5930 void unmount() {
5931 super.unmount();
5932 state.dispose();
5933 assert(() {
5934 if (state._debugLifecycleState == _StateLifecycle.defunct) {
5935 return true;
5936 }
5937 throw FlutterError.fromParts(<DiagnosticsNode>[
5938 ErrorSummary('${state.runtimeType}.dispose failed to call super.dispose.'),
5939 ErrorDescription(
5940 'dispose() implementations must always call their superclass dispose() method, to ensure '
5941 'that all the resources used by the widget are fully released.',
5942 ),
5943 ]);
5944 }());
5945 state._element = null;
5946 // Release resources to reduce the severity of memory leaks caused by
5947 // defunct, but accidentally retained Elements.
5948 _state = null;
5949 }
5950
5951 @override
5952 InheritedWidget dependOnInheritedElement(Element ancestor, {Object? aspect}) {
5953 assert(() {
5954 final Type targetType = ancestor.widget.runtimeType;
5955 if (state._debugLifecycleState == _StateLifecycle.created) {
5956 throw FlutterError.fromParts(<DiagnosticsNode>[
5957 ErrorSummary(
5958 'dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called before ${state.runtimeType}.initState() completed.',
5959 ),
5960 ErrorDescription(
5961 'When an inherited widget changes, for example if the value of Theme.of() changes, '
5962 "its dependent widgets are rebuilt. If the dependent widget's reference to "
5963 'the inherited widget is in a constructor or an initState() method, '
5964 'then the rebuilt dependent widget will not reflect the changes in the '
5965 'inherited widget.',
5966 ),
5967 ErrorHint(
5968 'Typically references to inherited widgets should occur in widget build() methods. Alternatively, '
5969 'initialization based on inherited widgets can be placed in the didChangeDependencies method, which '
5970 'is called after initState and whenever the dependencies change thereafter.',
5971 ),
5972 ]);
5973 }
5974 if (state._debugLifecycleState == _StateLifecycle.defunct) {
5975 throw FlutterError.fromParts(<DiagnosticsNode>[
5976 ErrorSummary(
5977 'dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called after dispose(): $this',
5978 ),
5979 ErrorDescription(
5980 'This error happens if you call dependOnInheritedWidgetOfExactType() on the '
5981 'BuildContext for a widget that no longer appears in the widget tree '
5982 '(e.g., whose parent widget no longer includes the widget in its '
5983 'build). This error can occur when code calls '
5984 'dependOnInheritedWidgetOfExactType() from a timer or an animation callback.',
5985 ),
5986 ErrorHint(
5987 'The preferred solution is to cancel the timer or stop listening to the '
5988 'animation in the dispose() callback. Another solution is to check the '
5989 '"mounted" property of this object before calling '
5990 'dependOnInheritedWidgetOfExactType() to ensure the object is still in the '
5991 'tree.',
5992 ),
5993 ErrorHint(
5994 'This error might indicate a memory leak if '
5995 'dependOnInheritedWidgetOfExactType() is being called because another object '
5996 'is retaining a reference to this State object after it has been '
5997 'removed from the tree. To avoid memory leaks, consider breaking the '
5998 'reference to this object during dispose().',
5999 ),
6000 ]);
6001 }
6002 return true;
6003 }());
6004 return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
6005 }
6006
6007 /// This controls whether we should call [State.didChangeDependencies] from
6008 /// the start of [build], to avoid calls when the [State] will not get built.
6009 /// This can happen when the widget has dropped out of the tree, but depends
6010 /// on an [InheritedWidget] that is still in the tree.
6011 ///
6012 /// It is set initially to false, since [_firstBuild] makes the initial call
6013 /// on the [state]. When it is true, [build] will call
6014 /// `state.didChangeDependencies` and then sets it to false. Subsequent calls
6015 /// to [didChangeDependencies] set it to true.
6016 bool _didChangeDependencies = false;
6017
6018 @override
6019 void didChangeDependencies() {
6020 super.didChangeDependencies();
6021 _didChangeDependencies = true;
6022 }
6023
6024 @override
6025 DiagnosticsNode toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) {
6026 return _ElementDiagnosticableTreeNode(name: name, value: this, style: style, stateful: true);
6027 }
6028
6029 @override
6030 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
6031 super.debugFillProperties(properties);
6032 properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', _state, defaultValue: null));
6033 }
6034}
6035
6036/// An [Element] that uses a [ProxyWidget] as its configuration.
6037abstract class ProxyElement extends ComponentElement {
6038 /// Initializes fields for subclasses.
6039 ProxyElement(ProxyWidget super.widget);
6040
6041 @override
6042 Widget build() => (widget as ProxyWidget).child;
6043
6044 @override
6045 void update(ProxyWidget newWidget) {
6046 final ProxyWidget oldWidget = widget as ProxyWidget;
6047 assert(widget != newWidget);
6048 super.update(newWidget);
6049 assert(widget == newWidget);
6050 updated(oldWidget);
6051 rebuild(force: true);
6052 }
6053
6054 /// Called during build when the [widget] has changed.
6055 ///
6056 /// By default, calls [notifyClients]. Subclasses may override this method to
6057 /// avoid calling [notifyClients] unnecessarily (e.g. if the old and new
6058 /// widgets are equivalent).
6059 @protected
6060 void updated(covariant ProxyWidget oldWidget) {
6061 notifyClients(oldWidget);
6062 }
6063
6064 /// Notify other objects that the widget associated with this element has
6065 /// changed.
6066 ///
6067 /// Called during [update] (via [updated]) after changing the widget
6068 /// associated with this element but before rebuilding this element.
6069 @protected
6070 void notifyClients(covariant ProxyWidget oldWidget);
6071}
6072
6073/// An [Element] that uses a [ParentDataWidget] as its configuration.
6074class ParentDataElement<T extends ParentData> extends ProxyElement {
6075 /// Creates an element that uses the given widget as its configuration.
6076 ParentDataElement(ParentDataWidget<T> super.widget);
6077
6078 /// Returns the [Type] of [ParentData] that this element has been configured
6079 /// for.
6080 ///
6081 /// This is only available in debug mode. It will throw in profile and
6082 /// release modes.
6083 Type get debugParentDataType {
6084 Type? type;
6085 assert(() {
6086 type = T;
6087 return true;
6088 }());
6089 if (type != null) {
6090 return type!;
6091 }
6092 throw UnsupportedError('debugParentDataType is only supported in debug builds');
6093 }
6094
6095 void _applyParentData(ParentDataWidget<T> widget) {
6096 void applyParentDataToChild(Element child) {
6097 if (child is RenderObjectElement) {
6098 child._updateParentData(widget);
6099 } else if (child.renderObjectAttachingChild != null) {
6100 applyParentDataToChild(child.renderObjectAttachingChild!);
6101 }
6102 }
6103
6104 if (renderObjectAttachingChild != null) {
6105 applyParentDataToChild(renderObjectAttachingChild!);
6106 }
6107 }
6108
6109 /// Calls [ParentDataWidget.applyParentData] on the given widget, passing it
6110 /// the [RenderObject] whose parent data this element is ultimately
6111 /// responsible for.
6112 ///
6113 /// This allows a render object's [RenderObject.parentData] to be modified
6114 /// without triggering a build. This is generally ill-advised, but makes sense
6115 /// in situations such as the following:
6116 ///
6117 /// * Build and layout are currently under way, but the [ParentData] in question
6118 /// does not affect layout, and the value to be applied could not be
6119 /// determined before build and layout (e.g. it depends on the layout of a
6120 /// descendant).
6121 ///
6122 /// * Paint is currently under way, but the [ParentData] in question does not
6123 /// affect layout or paint, and the value to be applied could not be
6124 /// determined before paint (e.g. it depends on the compositing phase).
6125 ///
6126 /// In either case, the next build is expected to cause this element to be
6127 /// configured with the given new widget (or a widget with equivalent data).
6128 ///
6129 /// Only [ParentDataWidget]s that return true for
6130 /// [ParentDataWidget.debugCanApplyOutOfTurn] can be applied this way.
6131 ///
6132 /// The new widget must have the same child as the current widget.
6133 ///
6134 /// An example of when this is used is the [AutomaticKeepAlive] widget. If it
6135 /// receives a notification during the build of one of its descendants saying
6136 /// that its child must be kept alive, it will apply a [KeepAlive] widget out
6137 /// of turn. This is safe, because by definition the child is already alive,
6138 /// and therefore this will not change the behavior of the parent this frame.
6139 /// It is more efficient than requesting an additional frame just for the
6140 /// purpose of updating the [KeepAlive] widget.
6141 void applyWidgetOutOfTurn(ParentDataWidget<T> newWidget) {
6142 assert(newWidget.debugCanApplyOutOfTurn());
6143 assert(newWidget.child == (widget as ParentDataWidget<T>).child);
6144 _applyParentData(newWidget);
6145 }
6146
6147 @override
6148 void notifyClients(ParentDataWidget<T> oldWidget) {
6149 _applyParentData(widget as ParentDataWidget<T>);
6150 }
6151}
6152
6153/// An [Element] that uses an [InheritedWidget] as its configuration.
6154class InheritedElement extends ProxyElement {
6155 /// Creates an element that uses the given widget as its configuration.
6156 InheritedElement(InheritedWidget super.widget);
6157
6158 final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
6159
6160 @override
6161 void _updateInheritance() {
6162 assert(_lifecycleState == _ElementLifecycle.active);
6163 final PersistentHashMap<Type, InheritedElement> incomingWidgets =
6164 _parent?._inheritedElements ?? const PersistentHashMap<Type, InheritedElement>.empty();
6165 _inheritedElements = incomingWidgets.put(widget.runtimeType, this);
6166 }
6167
6168 @override
6169 void debugDeactivated() {
6170 assert(() {
6171 assert(_dependents.isEmpty);
6172 return true;
6173 }());
6174 super.debugDeactivated();
6175 }
6176
6177 /// Returns the dependencies value recorded for [dependent]
6178 /// with [setDependencies].
6179 ///
6180 /// Each dependent element is mapped to a single object value
6181 /// which represents how the element depends on this
6182 /// [InheritedElement]. This value is null by default and by default
6183 /// dependent elements are rebuilt unconditionally.
6184 ///
6185 /// Subclasses can manage these values with [updateDependencies]
6186 /// so that they can selectively rebuild dependents in
6187 /// [notifyDependent].
6188 ///
6189 /// This method is typically only called in overrides of [updateDependencies].
6190 ///
6191 /// See also:
6192 ///
6193 /// * [updateDependencies], which is called each time a dependency is
6194 /// created with [dependOnInheritedWidgetOfExactType].
6195 /// * [setDependencies], which sets dependencies value for a dependent
6196 /// element.
6197 /// * [notifyDependent], which can be overridden to use a dependent's
6198 /// dependencies value to decide if the dependent needs to be rebuilt.
6199 /// * [InheritedModel], which is an example of a class that uses this method
6200 /// to manage dependency values.
6201 @protected
6202 Object? getDependencies(Element dependent) {
6203 return _dependents[dependent];
6204 }
6205
6206 /// Sets the value returned by [getDependencies] value for [dependent].
6207 ///
6208 /// Each dependent element is mapped to a single object value
6209 /// which represents how the element depends on this
6210 /// [InheritedElement]. The [updateDependencies] method sets this value to
6211 /// null by default so that dependent elements are rebuilt unconditionally.
6212 ///
6213 /// Subclasses can manage these values with [updateDependencies]
6214 /// so that they can selectively rebuild dependents in [notifyDependent].
6215 ///
6216 /// This method is typically only called in overrides of [updateDependencies].
6217 ///
6218 /// See also:
6219 ///
6220 /// * [updateDependencies], which is called each time a dependency is
6221 /// created with [dependOnInheritedWidgetOfExactType].
6222 /// * [getDependencies], which returns the current value for a dependent
6223 /// element.
6224 /// * [notifyDependent], which can be overridden to use a dependent's
6225 /// [getDependencies] value to decide if the dependent needs to be rebuilt.
6226 /// * [InheritedModel], which is an example of a class that uses this method
6227 /// to manage dependency values.
6228 @protected
6229 void setDependencies(Element dependent, Object? value) {
6230 _dependents[dependent] = value;
6231 }
6232
6233 /// Called by [dependOnInheritedWidgetOfExactType] when a new [dependent] is added.
6234 ///
6235 /// Each dependent element can be mapped to a single object value with
6236 /// [setDependencies]. This method can lookup the existing dependencies with
6237 /// [getDependencies].
6238 ///
6239 /// By default this method sets the inherited dependencies for [dependent]
6240 /// to null. This only serves to record an unconditional dependency on
6241 /// [dependent].
6242 ///
6243 /// Subclasses can manage their own dependencies values so that they
6244 /// can selectively rebuild dependents in [notifyDependent].
6245 ///
6246 /// See also:
6247 ///
6248 /// * [getDependencies], which returns the current value for a dependent
6249 /// element.
6250 /// * [setDependencies], which sets the value for a dependent element.
6251 /// * [notifyDependent], which can be overridden to use a dependent's
6252 /// dependencies value to decide if the dependent needs to be rebuilt.
6253 /// * [InheritedModel], which is an example of a class that uses this method
6254 /// to manage dependency values.
6255 @protected
6256 void updateDependencies(Element dependent, Object? aspect) {
6257 setDependencies(dependent, null);
6258 }
6259
6260 /// Called by [notifyClients] for each dependent.
6261 ///
6262 /// Calls `dependent.didChangeDependencies()` by default.
6263 ///
6264 /// Subclasses can override this method to selectively call
6265 /// [didChangeDependencies] based on the value of [getDependencies].
6266 ///
6267 /// See also:
6268 ///
6269 /// * [updateDependencies], which is called each time a dependency is
6270 /// created with [dependOnInheritedWidgetOfExactType].
6271 /// * [getDependencies], which returns the current value for a dependent
6272 /// element.
6273 /// * [setDependencies], which sets the value for a dependent element.
6274 /// * [InheritedModel], which is an example of a class that uses this method
6275 /// to manage dependency values.
6276 @protected
6277 void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
6278 dependent.didChangeDependencies();
6279 }
6280
6281 /// Called by [Element.deactivate] to remove the provided `dependent` [Element] from this [InheritedElement].
6282 ///
6283 /// After the dependent is removed, [Element.didChangeDependencies] will no
6284 /// longer be called on it when this [InheritedElement] notifies its dependents.
6285 ///
6286 /// Subclasses can override this method to release any resources retained for
6287 /// a given [dependent].
6288 @protected
6289 @mustCallSuper
6290 void removeDependent(Element dependent) {
6291 _dependents.remove(dependent);
6292 }
6293
6294 /// Calls [Element.didChangeDependencies] of all dependent elements, if
6295 /// [InheritedWidget.updateShouldNotify] returns true.
6296 ///
6297 /// Called by [update], immediately prior to [build].
6298 ///
6299 /// Calls [notifyClients] to actually trigger the notifications.
6300 @override
6301 void updated(InheritedWidget oldWidget) {
6302 if ((widget as InheritedWidget).updateShouldNotify(oldWidget)) {
6303 super.updated(oldWidget);
6304 }
6305 }
6306
6307 /// Notifies all dependent elements that this inherited widget has changed, by
6308 /// calling [Element.didChangeDependencies].
6309 ///
6310 /// This method must only be called during the build phase. Usually this
6311 /// method is called automatically when an inherited widget is rebuilt, e.g.
6312 /// as a result of calling [State.setState] above the inherited widget.
6313 ///
6314 /// See also:
6315 ///
6316 /// * [InheritedNotifier], a subclass of [InheritedWidget] that also calls
6317 /// this method when its [Listenable] sends a notification.
6318 @override
6319 void notifyClients(InheritedWidget oldWidget) {
6320 assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
6321 for (final Element dependent in _dependents.keys) {
6322 assert(() {
6323 // check that it really is our descendant
6324 Element? ancestor = dependent._parent;
6325 while (ancestor != this && ancestor != null) {
6326 ancestor = ancestor._parent;
6327 }
6328 return ancestor == this;
6329 }());
6330 // check that it really depends on us
6331 assert(dependent._dependencies!.contains(this));
6332 notifyDependent(oldWidget, dependent);
6333 }
6334 }
6335}
6336
6337/// An [Element] that uses a [RenderObjectWidget] as its configuration.
6338///
6339/// [RenderObjectElement] objects have an associated [RenderObject] widget in
6340/// the render tree, which handles concrete operations like laying out,
6341/// painting, and hit testing.
6342///
6343/// Contrast with [ComponentElement].
6344///
6345/// For details on the lifecycle of an element, see the discussion at [Element].
6346///
6347/// ## Writing a RenderObjectElement subclass
6348///
6349/// There are three common child models used by most [RenderObject]s:
6350///
6351/// * Leaf render objects, with no children: The [LeafRenderObjectElement] class
6352/// handles this case.
6353///
6354/// * A single child: The [SingleChildRenderObjectElement] class handles this
6355/// case.
6356///
6357/// * A linked list of children: The [MultiChildRenderObjectElement] class
6358/// handles this case.
6359///
6360/// Sometimes, however, a render object's child model is more complicated. Maybe
6361/// it has a two-dimensional array of children. Maybe it constructs children on
6362/// demand. Maybe it features multiple lists. In such situations, the
6363/// corresponding [Element] for the [Widget] that configures that [RenderObject]
6364/// will be a new subclass of [RenderObjectElement].
6365///
6366/// Such a subclass is responsible for managing children, specifically the
6367/// [Element] children of this object, and the [RenderObject] children of its
6368/// corresponding [RenderObject].
6369///
6370/// ### Specializing the getters
6371///
6372/// [RenderObjectElement] objects spend much of their time acting as
6373/// intermediaries between their [widget] and their [renderObject]. It is
6374/// generally recommended against specializing the [widget] getter and
6375/// instead casting at the various call sites to avoid adding overhead
6376/// outside of this particular implementation.
6377///
6378/// ```dart
6379/// class FooElement extends RenderObjectElement {
6380/// FooElement(super.widget);
6381///
6382/// // Specializing the renderObject getter is fine because
6383/// // it is not performance sensitive.
6384/// @override
6385/// RenderFoo get renderObject => super.renderObject as RenderFoo;
6386///
6387/// void _foo() {
6388/// // For the widget getter, though, we prefer to cast locally
6389/// // since that results in better overall performance where the
6390/// // casting isn't needed:
6391/// final Foo foo = widget as Foo;
6392/// // ...
6393/// }
6394///
6395/// // ...
6396/// }
6397/// ```
6398///
6399/// ### Slots
6400///
6401/// Each child [Element] corresponds to a [RenderObject] which should be
6402/// attached to this element's render object as a child.
6403///
6404/// However, the immediate children of the element may not be the ones that
6405/// eventually produce the actual [RenderObject] that they correspond to. For
6406/// example, a [StatelessElement] (the element of a [StatelessWidget])
6407/// corresponds to whatever [RenderObject] its child (the element returned by
6408/// its [StatelessWidget.build] method) corresponds to.
6409///
6410/// Each child is therefore assigned a _[slot]_ token. This is an identifier whose
6411/// meaning is private to this [RenderObjectElement] node. When the descendant
6412/// that finally produces the [RenderObject] is ready to attach it to this
6413/// node's render object, it passes that slot token back to this node, and that
6414/// allows this node to cheaply identify where to put the child render object
6415/// relative to the others in the parent render object.
6416///
6417/// A child's [slot] is determined when the parent calls [updateChild] to
6418/// inflate the child (see the next section). It can be updated by calling
6419/// [updateSlotForChild].
6420///
6421/// ### Updating children
6422///
6423/// Early in the lifecycle of an element, the framework calls the [mount]
6424/// method. This method should call [updateChild] for each child, passing in
6425/// the widget for that child, and the slot for that child, thus obtaining a
6426/// list of child [Element]s.
6427///
6428/// Subsequently, the framework will call the [update] method. In this method,
6429/// the [RenderObjectElement] should call [updateChild] for each child, passing
6430/// in the [Element] that was obtained during [mount] or the last time [update]
6431/// was run (whichever happened most recently), the new [Widget], and the slot.
6432/// This provides the object with a new list of [Element] objects.
6433///
6434/// Where possible, the [update] method should attempt to map the elements from
6435/// the last pass to the widgets in the new pass. For example, if one of the
6436/// elements from the last pass was configured with a particular [Key], and one
6437/// of the widgets in this new pass has that same key, they should be paired up,
6438/// and the old element should be updated with the widget (and the slot
6439/// corresponding to the new widget's new position, also). The [updateChildren]
6440/// method may be useful in this regard.
6441///
6442/// [updateChild] should be called for children in their logical order. The
6443/// order can matter; for example, if two of the children use [PageStorage]'s
6444/// `writeState` feature in their build method (and neither has a [Widget.key]),
6445/// then the state written by the first will be overwritten by the second.
6446///
6447/// #### Dynamically determining the children during the build phase
6448///
6449/// The child widgets need not necessarily come from this element's widget
6450/// verbatim. They could be generated dynamically from a callback, or generated
6451/// in other more creative ways.
6452///
6453/// #### Dynamically determining the children during layout
6454///
6455/// If the widgets are to be generated at layout time, then generating them in
6456/// the [mount] and [update] methods won't work: layout of this element's render
6457/// object hasn't started yet at that point. Instead, the [update] method can
6458/// mark the render object as needing layout (see
6459/// [RenderObject.markNeedsLayout]), and then the render object's
6460/// [RenderObject.performLayout] method can call back to the element to have it
6461/// generate the widgets and call [updateChild] accordingly.
6462///
6463/// For a render object to call an element during layout, it must use
6464/// [RenderObject.invokeLayoutCallback]. For an element to call [updateChild]
6465/// outside of its [update] method, it must use [BuildOwner.buildScope].
6466///
6467/// The framework provides many more checks in normal operation than it does
6468/// when doing a build during layout. For this reason, creating widgets with
6469/// layout-time build semantics should be done with great care.
6470///
6471/// #### Handling errors when building
6472///
6473/// If an element calls a builder function to obtain widgets for its children,
6474/// it may find that the build throws an exception. Such exceptions should be
6475/// caught and reported using [FlutterError.reportError]. If a child is needed
6476/// but a builder has failed in this way, an instance of [ErrorWidget] can be
6477/// used instead.
6478///
6479/// ### Detaching children
6480///
6481/// It is possible, when using [GlobalKey]s, for a child to be proactively
6482/// removed by another element before this element has been updated.
6483/// (Specifically, this happens when the subtree rooted at a widget with a
6484/// particular [GlobalKey] is being moved from this element to an element
6485/// processed earlier in the build phase.) When this happens, this element's
6486/// [forgetChild] method will be called with a reference to the affected child
6487/// element.
6488///
6489/// The [forgetChild] method of a [RenderObjectElement] subclass must remove the
6490/// child element from its child list, so that when it next [update]s its
6491/// children, the removed child is not considered.
6492///
6493/// For performance reasons, if there are many elements, it may be quicker to
6494/// track which elements were forgotten by storing them in a [Set], rather than
6495/// proactively mutating the local record of the child list and the identities
6496/// of all the slots. For example, see the implementation of
6497/// [MultiChildRenderObjectElement].
6498///
6499/// ### Maintaining the render object tree
6500///
6501/// Once a descendant produces a render object, it will call
6502/// [insertRenderObjectChild]. If the descendant's slot changes identity, it
6503/// will call [moveRenderObjectChild]. If a descendant goes away, it will call
6504/// [removeRenderObjectChild].
6505///
6506/// These three methods should update the render tree accordingly, attaching,
6507/// moving, and detaching the given child render object from this element's own
6508/// render object respectively.
6509///
6510/// ### Walking the children
6511///
6512/// If a [RenderObjectElement] object has any children [Element]s, it must
6513/// expose them in its implementation of the [visitChildren] method. This method
6514/// is used by many of the framework's internal mechanisms, and so should be
6515/// fast. It is also used by the test framework and [debugDumpApp].
6516abstract class RenderObjectElement extends Element {
6517 /// Creates an element that uses the given widget as its configuration.
6518 RenderObjectElement(RenderObjectWidget super.widget);
6519
6520 /// The underlying [RenderObject] for this element.
6521 ///
6522 /// If this element has been [unmount]ed, this getter will throw.
6523 @override
6524 RenderObject get renderObject {
6525 assert(_renderObject != null, '$runtimeType unmounted');
6526 return _renderObject!;
6527 }
6528
6529 RenderObject? _renderObject;
6530
6531 @override
6532 Element? get renderObjectAttachingChild => null;
6533
6534 bool _debugDoingBuild = false;
6535 @override
6536 bool get debugDoingBuild => _debugDoingBuild;
6537
6538 RenderObjectElement? _ancestorRenderObjectElement;
6539
6540 RenderObjectElement? _findAncestorRenderObjectElement() {
6541 Element? ancestor = _parent;
6542 while (ancestor != null && ancestor is! RenderObjectElement) {
6543 // In debug mode we check whether the ancestor accepts RenderObjects to
6544 // produce a better error message in attachRenderObject. In release mode,
6545 // we assume only correct trees are built (i.e.
6546 // debugExpectsRenderObjectForSlot always returns true) and don't check
6547 // explicitly.
6548 assert(() {
6549 if (!ancestor!.debugExpectsRenderObjectForSlot(slot)) {
6550 ancestor = null;
6551 }
6552 return true;
6553 }());
6554 ancestor = ancestor?._parent;
6555 }
6556 assert(() {
6557 if (ancestor?.debugExpectsRenderObjectForSlot(slot) == false) {
6558 ancestor = null;
6559 }
6560 return true;
6561 }());
6562 return ancestor as RenderObjectElement?;
6563 }
6564
6565 void _debugCheckCompetingAncestors(
6566 List<ParentDataElement<ParentData>> result,
6567 Set<Type> debugAncestorTypes,
6568 Set<Type> debugParentDataTypes,
6569 List<Type> debugAncestorCulprits,
6570 ) {
6571 assert(() {
6572 // Check that no other ParentDataWidgets of the same
6573 // type want to provide parent data.
6574 if (debugAncestorTypes.length != result.length ||
6575 debugParentDataTypes.length != result.length) {
6576 // This can only occur if the Sets of ancestors and parent data types was
6577 // provided a dupe and did not add it.
6578 assert(
6579 debugAncestorTypes.length < result.length || debugParentDataTypes.length < result.length,
6580 );
6581 try {
6582 // We explicitly throw here (even though we immediately redirect the
6583 // exception elsewhere) so that debuggers will notice it when they
6584 // have "break on exception" enabled.
6585 throw FlutterError.fromParts(<DiagnosticsNode>[
6586 ErrorSummary('Incorrect use of ParentDataWidget.'),
6587 ErrorDescription(
6588 'Competing ParentDataWidgets are providing parent data to the '
6589 'same RenderObject:',
6590 ),
6591 for (final ParentDataElement<ParentData> ancestor in result.where((
6592 ParentDataElement<ParentData> ancestor,
6593 ) {
6594 return debugAncestorCulprits.contains(ancestor.runtimeType);
6595 }))
6596 ErrorDescription(
6597 '- ${ancestor.widget}, which writes ParentData of type '
6598 '${ancestor.debugParentDataType}, (typically placed directly '
6599 'inside a '
6600 '${(ancestor.widget as ParentDataWidget<ParentData>).debugTypicalAncestorWidgetClass} '
6601 'widget)',
6602 ),
6603 ErrorDescription(
6604 'A RenderObject can receive parent data from multiple '
6605 'ParentDataWidgets, but the Type of ParentData must be unique to '
6606 'prevent one overwriting another.',
6607 ),
6608 ErrorHint(
6609 'Usually, this indicates that one or more of the offending '
6610 "ParentDataWidgets listed above isn't placed inside a dedicated "
6611 "compatible ancestor widget that it isn't sharing with another "
6612 'ParentDataWidget of the same type.',
6613 ),
6614 ErrorHint(
6615 'Otherwise, separating aspects of ParentData to prevent '
6616 'conflicts can be done using mixins, mixing them all in on the '
6617 'full ParentData Object, such as KeepAlive does with '
6618 'KeepAliveParentDataMixin.',
6619 ),
6620 ErrorDescription(
6621 'The ownership chain for the RenderObject that received the '
6622 'parent data was:\n ${debugGetCreatorChain(10)}',
6623 ),
6624 ]);
6625 } on FlutterError catch (error) {
6626 _reportException(ErrorSummary('while looking for parent data.'), error, error.stackTrace);
6627 }
6628 }
6629 return true;
6630 }());
6631 }
6632
6633 List<ParentDataElement<ParentData>> _findAncestorParentDataElements() {
6634 Element? ancestor = _parent;
6635 final List<ParentDataElement<ParentData>> result = <ParentDataElement<ParentData>>[];
6636 final Set<Type> debugAncestorTypes = <Type>{};
6637 final Set<Type> debugParentDataTypes = <Type>{};
6638 final List<Type> debugAncestorCulprits = <Type>[];
6639
6640 // More than one ParentDataWidget can contribute ParentData, but there are
6641 // some constraints.
6642 // 1. ParentData can only be written by unique ParentDataWidget types.
6643 // For example, two KeepAlive ParentDataWidgets trying to write to the
6644 // same child is not allowed.
6645 // 2. Each contributing ParentDataWidget must contribute to a unique
6646 // ParentData type, less ParentData be overwritten.
6647 // For example, there cannot be two ParentDataWidgets that both write
6648 // ParentData of type KeepAliveParentDataMixin, if the first check was
6649 // subverted by a subclassing of the KeepAlive ParentDataWidget.
6650 // 3. The ParentData itself must be compatible with all ParentDataWidgets
6651 // writing to it.
6652 // For example, TwoDimensionalViewportParentData uses the
6653 // KeepAliveParentDataMixin, so it could be compatible with both
6654 // KeepAlive, and another ParentDataWidget with ParentData type
6655 // TwoDimensionalViewportParentData or a subclass thereof.
6656 // The first and second cases are verified here. The third is verified in
6657 // debugIsValidRenderObject.
6658
6659 while (ancestor != null && ancestor is! RenderObjectElement) {
6660 if (ancestor is ParentDataElement<ParentData>) {
6661 assert((ParentDataElement<ParentData> ancestor) {
6662 if (!debugAncestorTypes.add(ancestor.runtimeType) ||
6663 !debugParentDataTypes.add(ancestor.debugParentDataType)) {
6664 debugAncestorCulprits.add(ancestor.runtimeType);
6665 }
6666 return true;
6667 }(ancestor));
6668 result.add(ancestor);
6669 }
6670 ancestor = ancestor._parent;
6671 }
6672 assert(() {
6673 if (result.isEmpty || ancestor == null) {
6674 return true;
6675 }
6676 // Validate points 1 and 2 from above.
6677 _debugCheckCompetingAncestors(
6678 result,
6679 debugAncestorTypes,
6680 debugParentDataTypes,
6681 debugAncestorCulprits,
6682 );
6683 return true;
6684 }());
6685 return result;
6686 }
6687
6688 @override
6689 void mount(Element? parent, Object? newSlot) {
6690 super.mount(parent, newSlot);
6691 assert(() {
6692 _debugDoingBuild = true;
6693 return true;
6694 }());
6695 _renderObject = (widget as RenderObjectWidget).createRenderObject(this);
6696 assert(!_renderObject!.debugDisposed!);
6697 assert(() {
6698 _debugDoingBuild = false;
6699 return true;
6700 }());
6701 assert(() {
6702 _debugUpdateRenderObjectOwner();
6703 return true;
6704 }());
6705 assert(slot == newSlot);
6706 attachRenderObject(newSlot);
6707 super.performRebuild(); // clears the "dirty" flag
6708 }
6709
6710 @override
6711 void update(covariant RenderObjectWidget newWidget) {
6712 super.update(newWidget);
6713 assert(widget == newWidget);
6714 assert(() {
6715 _debugUpdateRenderObjectOwner();
6716 return true;
6717 }());
6718 _performRebuild(); // calls widget.updateRenderObject()
6719 }
6720
6721 void _debugUpdateRenderObjectOwner() {
6722 assert(() {
6723 renderObject.debugCreator = DebugCreator(this);
6724 return true;
6725 }());
6726 }
6727
6728 @override
6729 // ignore: must_call_super, _performRebuild calls super.
6730 void performRebuild() {
6731 _performRebuild(); // calls widget.updateRenderObject()
6732 }
6733
6734 @pragma('dart2js:tryInline')
6735 @pragma('vm:prefer-inline')
6736 @pragma('wasm:prefer-inline')
6737 void _performRebuild() {
6738 assert(() {
6739 _debugDoingBuild = true;
6740 return true;
6741 }());
6742 (widget as RenderObjectWidget).updateRenderObject(this, renderObject);
6743 assert(() {
6744 _debugDoingBuild = false;
6745 return true;
6746 }());
6747 super.performRebuild(); // clears the "dirty" flag
6748 }
6749
6750 @override
6751 void deactivate() {
6752 super.deactivate();
6753 assert(
6754 !renderObject.attached,
6755 'A RenderObject was still attached when attempting to deactivate its '
6756 'RenderObjectElement: $renderObject',
6757 );
6758 }
6759
6760 @override
6761 void unmount() {
6762 assert(
6763 !renderObject.debugDisposed!,
6764 'A RenderObject was disposed prior to its owning element being unmounted: '
6765 '$renderObject',
6766 );
6767 final RenderObjectWidget oldWidget = widget as RenderObjectWidget;
6768 super.unmount();
6769 assert(
6770 !renderObject.attached,
6771 'A RenderObject was still attached when attempting to unmount its '
6772 'RenderObjectElement: $renderObject',
6773 );
6774 oldWidget.didUnmountRenderObject(renderObject);
6775 _renderObject!.dispose();
6776 _renderObject = null;
6777 }
6778
6779 void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) {
6780 bool applyParentData = true;
6781 assert(() {
6782 try {
6783 if (!parentDataWidget.debugIsValidRenderObject(renderObject)) {
6784 applyParentData = false;
6785 throw FlutterError.fromParts(<DiagnosticsNode>[
6786 ErrorSummary('Incorrect use of ParentDataWidget.'),
6787 ...parentDataWidget._debugDescribeIncorrectParentDataType(
6788 parentData: renderObject.parentData,
6789 parentDataCreator: _ancestorRenderObjectElement?.widget as RenderObjectWidget?,
6790 ownershipChain: ErrorDescription(debugGetCreatorChain(10)),
6791 ),
6792 ]);
6793 }
6794 } on FlutterError catch (e) {
6795 // We catch the exception directly to avoid activating the ErrorWidget,
6796 // while still allowing debuggers to break on exception. Since the tree
6797 // is in a broken state, adding the ErrorWidget would likely cause more
6798 // exceptions, which is not good for the debugging experience.
6799 _reportException(ErrorSummary('while applying parent data.'), e, e.stackTrace);
6800 }
6801 return true;
6802 }());
6803 if (applyParentData) {
6804 parentDataWidget.applyParentData(renderObject);
6805 }
6806 }
6807
6808 @override
6809 void updateSlot(Object? newSlot) {
6810 final Object? oldSlot = slot;
6811 assert(oldSlot != newSlot);
6812 super.updateSlot(newSlot);
6813 assert(slot == newSlot);
6814 assert(_ancestorRenderObjectElement == _findAncestorRenderObjectElement());
6815 _ancestorRenderObjectElement?.moveRenderObjectChild(renderObject, oldSlot, slot);
6816 }
6817
6818 @override
6819 void attachRenderObject(Object? newSlot) {
6820 assert(_ancestorRenderObjectElement == null);
6821 _slot = newSlot;
6822 _ancestorRenderObjectElement = _findAncestorRenderObjectElement();
6823 assert(() {
6824 if (_ancestorRenderObjectElement == null) {
6825 FlutterError.reportError(
6826 FlutterErrorDetails(
6827 exception: FlutterError.fromParts(<DiagnosticsNode>[
6828 ErrorSummary(
6829 'The render object for ${toStringShort()} cannot find ancestor render object to attach to.',
6830 ),
6831 ErrorDescription(
6832 'The ownership chain for the RenderObject in question was:\n ${debugGetCreatorChain(10)}',
6833 ),
6834 ErrorHint(
6835 'Try wrapping your widget in a View widget or any other widget that is backed by '
6836 'a $RenderTreeRootElement to serve as the root of the render tree.',
6837 ),
6838 ]),
6839 ),
6840 );
6841 }
6842 return true;
6843 }());
6844 _ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
6845 final List<ParentDataElement<ParentData>> parentDataElements =
6846 _findAncestorParentDataElements();
6847 for (final ParentDataElement<ParentData> parentDataElement in parentDataElements) {
6848 _updateParentData(parentDataElement.widget as ParentDataWidget<ParentData>);
6849 }
6850 }
6851
6852 @override
6853 void detachRenderObject() {
6854 if (_ancestorRenderObjectElement != null) {
6855 _ancestorRenderObjectElement!.removeRenderObjectChild(renderObject, slot);
6856 _ancestorRenderObjectElement = null;
6857 }
6858 _slot = null;
6859 }
6860
6861 /// Insert the given child into [renderObject] at the given slot.
6862 ///
6863 /// {@template flutter.widgets.RenderObjectElement.insertRenderObjectChild}
6864 /// The semantics of `slot` are determined by this element. For example, if
6865 /// this element has a single child, the slot should always be null. If this
6866 /// element has a list of children, the previous sibling element wrapped in an
6867 /// [IndexedSlot] is a convenient value for the slot.
6868 /// {@endtemplate}
6869 @protected
6870 void insertRenderObjectChild(covariant RenderObject child, covariant Object? slot);
6871
6872 /// Move the given child from the given old slot to the given new slot.
6873 ///
6874 /// The given child is guaranteed to have [renderObject] as its parent.
6875 ///
6876 /// {@macro flutter.widgets.RenderObjectElement.insertRenderObjectChild}
6877 ///
6878 /// This method is only ever called if [updateChild] can end up being called
6879 /// with an existing [Element] child and a `slot` that differs from the slot
6880 /// that element was previously given. [MultiChildRenderObjectElement] does this,
6881 /// for example. [SingleChildRenderObjectElement] does not (since the `slot` is
6882 /// always null). An [Element] that has a specific set of slots with each child
6883 /// always having the same slot (and where children in different slots are never
6884 /// compared against each other for the purposes of updating one slot with the
6885 /// element from another slot) would never call this.
6886 @protected
6887 void moveRenderObjectChild(
6888 covariant RenderObject child,
6889 covariant Object? oldSlot,
6890 covariant Object? newSlot,
6891 );
6892
6893 /// Remove the given child from [renderObject].
6894 ///
6895 /// The given child is guaranteed to have been inserted at the given `slot`
6896 /// and have [renderObject] as its parent.
6897 @protected
6898 void removeRenderObjectChild(covariant RenderObject child, covariant Object? slot);
6899
6900 @override
6901 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
6902 super.debugFillProperties(properties);
6903 properties.add(
6904 DiagnosticsProperty<RenderObject>('renderObject', _renderObject, defaultValue: null),
6905 );
6906 }
6907}
6908
6909/// Deprecated. Unused in the framework and will be removed in a future version
6910/// of Flutter.
6911///
6912/// Classes that extend this class can extend [RenderObjectElement] and mixin
6913/// [RootElementMixin] instead.
6914@Deprecated(
6915 'Use RootElementMixin instead. '
6916 'This feature was deprecated after v3.9.0-16.0.pre.',
6917)
6918abstract class RootRenderObjectElement extends RenderObjectElement with RootElementMixin {
6919 /// Initializes fields for subclasses.
6920 @Deprecated(
6921 'Use RootElementMixin instead. '
6922 'This feature was deprecated after v3.9.0-16.0.pre.',
6923 )
6924 RootRenderObjectElement(super.widget);
6925}
6926
6927/// Mixin for the element at the root of the tree.
6928///
6929/// Only root elements may have their owner set explicitly. All other
6930/// elements inherit their owner from their parent.
6931mixin RootElementMixin on Element {
6932 /// Set the owner of the element. The owner will be propagated to all the
6933 /// descendants of this element.
6934 ///
6935 /// The owner manages the dirty elements list.
6936 ///
6937 /// The [WidgetsBinding] introduces the primary owner,
6938 /// [WidgetsBinding.buildOwner], and assigns it to the widget tree in the call
6939 /// to [runApp]. The binding is responsible for driving the build pipeline by
6940 /// calling the build owner's [BuildOwner.buildScope] method. See
6941 /// [WidgetsBinding.drawFrame].
6942 void assignOwner(BuildOwner owner) {
6943 _owner = owner;
6944 _parentBuildScope = BuildScope();
6945 }
6946
6947 @override
6948 void mount(Element? parent, Object? newSlot) {
6949 // Root elements should never have parents.
6950 assert(parent == null);
6951 assert(newSlot == null);
6952 super.mount(parent, newSlot);
6953 }
6954}
6955
6956/// An [Element] that uses a [LeafRenderObjectWidget] as its configuration.
6957class LeafRenderObjectElement extends RenderObjectElement {
6958 /// Creates an element that uses the given widget as its configuration.
6959 LeafRenderObjectElement(LeafRenderObjectWidget super.widget);
6960
6961 @override
6962 void forgetChild(Element child) {
6963 assert(false);
6964 super.forgetChild(child);
6965 }
6966
6967 @override
6968 void insertRenderObjectChild(RenderObject child, Object? slot) {
6969 assert(false);
6970 }
6971
6972 @override
6973 void moveRenderObjectChild(RenderObject child, Object? oldSlot, Object? newSlot) {
6974 assert(false);
6975 }
6976
6977 @override
6978 void removeRenderObjectChild(RenderObject child, Object? slot) {
6979 assert(false);
6980 }
6981
6982 @override
6983 List<DiagnosticsNode> debugDescribeChildren() {
6984 return widget.debugDescribeChildren();
6985 }
6986}
6987
6988/// An [Element] that uses a [SingleChildRenderObjectWidget] as its configuration.
6989///
6990/// The child is optional.
6991///
6992/// This element subclass can be used for [RenderObjectWidget]s whose
6993/// [RenderObject]s use the [RenderObjectWithChildMixin] mixin. Such widgets are
6994/// expected to inherit from [SingleChildRenderObjectWidget].
6995class SingleChildRenderObjectElement extends RenderObjectElement {
6996 /// Creates an element that uses the given widget as its configuration.
6997 SingleChildRenderObjectElement(SingleChildRenderObjectWidget super.widget);
6998
6999 Element? _child;
7000
7001 @override
7002 void visitChildren(ElementVisitor visitor) {
7003 if (_child != null) {
7004 visitor(_child!);
7005 }
7006 }
7007
7008 @override
7009 void forgetChild(Element child) {
7010 assert(child == _child);
7011 _child = null;
7012 super.forgetChild(child);
7013 }
7014
7015 @override
7016 void mount(Element? parent, Object? newSlot) {
7017 super.mount(parent, newSlot);
7018 _child = updateChild(_child, (widget as SingleChildRenderObjectWidget).child, null);
7019 }
7020
7021 @override
7022 void update(SingleChildRenderObjectWidget newWidget) {
7023 super.update(newWidget);
7024 assert(widget == newWidget);
7025 _child = updateChild(_child, (widget as SingleChildRenderObjectWidget).child, null);
7026 }
7027
7028 @override
7029 void insertRenderObjectChild(RenderObject child, Object? slot) {
7030 final RenderObjectWithChildMixin<RenderObject> renderObject =
7031 this.renderObject as RenderObjectWithChildMixin<RenderObject>;
7032 assert(slot == null);
7033 assert(renderObject.debugValidateChild(child));
7034 renderObject.child = child;
7035 assert(renderObject == this.renderObject);
7036 }
7037
7038 @override
7039 void moveRenderObjectChild(RenderObject child, Object? oldSlot, Object? newSlot) {
7040 assert(false);
7041 }
7042
7043 @override
7044 void removeRenderObjectChild(RenderObject child, Object? slot) {
7045 final RenderObjectWithChildMixin<RenderObject> renderObject =
7046 this.renderObject as RenderObjectWithChildMixin<RenderObject>;
7047 assert(slot == null);
7048 assert(renderObject.child == child);
7049 renderObject.child = null;
7050 assert(renderObject == this.renderObject);
7051 }
7052}
7053
7054/// An [Element] that uses a [MultiChildRenderObjectWidget] as its configuration.
7055///
7056/// This element subclass can be used for [RenderObjectWidget]s whose
7057/// [RenderObject]s use the [ContainerRenderObjectMixin] mixin with a parent data
7058/// type that implements [ContainerParentDataMixin<RenderObject>]. Such widgets
7059/// are expected to inherit from [MultiChildRenderObjectWidget].
7060///
7061/// See also:
7062///
7063/// * [IndexedSlot], which is used as [Element.slot]s for the children of a
7064/// [MultiChildRenderObjectElement].
7065/// * [RenderObjectElement.updateChildren], which discusses why [IndexedSlot]
7066/// is used for the slots of the children.
7067class MultiChildRenderObjectElement extends RenderObjectElement {
7068 /// Creates an element that uses the given widget as its configuration.
7069 MultiChildRenderObjectElement(MultiChildRenderObjectWidget super.widget)
7070 : assert(!debugChildrenHaveDuplicateKeys(widget, widget.children));
7071
7072 @override
7073 ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>
7074 get renderObject {
7075 return super.renderObject
7076 as ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>;
7077 }
7078
7079 /// The current list of children of this element.
7080 ///
7081 /// This list is filtered to hide elements that have been forgotten (using
7082 /// [forgetChild]).
7083 @protected
7084 @visibleForTesting
7085 Iterable<Element> get children =>
7086 _children.where((Element child) => !_forgottenChildren.contains(child));
7087
7088 late List<Element> _children;
7089 // We keep a set of forgotten children to avoid O(n^2) work walking _children
7090 // repeatedly to remove children.
7091 final Set<Element> _forgottenChildren = HashSet<Element>();
7092
7093 @override
7094 void insertRenderObjectChild(RenderObject child, IndexedSlot<Element?> slot) {
7095 final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>
7096 renderObject = this.renderObject;
7097 assert(renderObject.debugValidateChild(child));
7098 renderObject.insert(child, after: slot.value?.renderObject);
7099 assert(renderObject == this.renderObject);
7100 }
7101
7102 @override
7103 void moveRenderObjectChild(
7104 RenderObject child,
7105 IndexedSlot<Element?> oldSlot,
7106 IndexedSlot<Element?> newSlot,
7107 ) {
7108 final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>
7109 renderObject = this.renderObject;
7110 assert(child.parent == renderObject);
7111 renderObject.move(child, after: newSlot.value?.renderObject);
7112 assert(renderObject == this.renderObject);
7113 }
7114
7115 @override
7116 void removeRenderObjectChild(RenderObject child, Object? slot) {
7117 final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>
7118 renderObject = this.renderObject;
7119 assert(child.parent == renderObject);
7120 renderObject.remove(child);
7121 assert(renderObject == this.renderObject);
7122 }
7123
7124 @override
7125 void visitChildren(ElementVisitor visitor) {
7126 for (final Element child in _children) {
7127 if (!_forgottenChildren.contains(child)) {
7128 visitor(child);
7129 }
7130 }
7131 }
7132
7133 @override
7134 void forgetChild(Element child) {
7135 assert(_children.contains(child));
7136 assert(!_forgottenChildren.contains(child));
7137 _forgottenChildren.add(child);
7138 super.forgetChild(child);
7139 }
7140
7141 bool _debugCheckHasAssociatedRenderObject(Element newChild) {
7142 assert(() {
7143 if (newChild.renderObject == null) {
7144 FlutterError.reportError(
7145 FlutterErrorDetails(
7146 exception: FlutterError.fromParts(<DiagnosticsNode>[
7147 ErrorSummary(
7148 'The children of `MultiChildRenderObjectElement` must each has an associated render object.',
7149 ),
7150 ErrorHint(
7151 'This typically means that the `${newChild.widget}` or its children\n'
7152 'are not a subtype of `RenderObjectWidget`.',
7153 ),
7154 newChild.describeElement(
7155 'The following element does not have an associated render object',
7156 ),
7157 DiagnosticsDebugCreator(DebugCreator(newChild)),
7158 ]),
7159 ),
7160 );
7161 }
7162 return true;
7163 }());
7164 return true;
7165 }
7166
7167 @override
7168 Element inflateWidget(Widget newWidget, Object? newSlot) {
7169 final Element newChild = super.inflateWidget(newWidget, newSlot);
7170 assert(_debugCheckHasAssociatedRenderObject(newChild));
7171 return newChild;
7172 }
7173
7174 @override
7175 void mount(Element? parent, Object? newSlot) {
7176 super.mount(parent, newSlot);
7177 final MultiChildRenderObjectWidget multiChildRenderObjectWidget =
7178 widget as MultiChildRenderObjectWidget;
7179 final List<Element> children = List<Element>.filled(
7180 multiChildRenderObjectWidget.children.length,
7181 _NullElement.instance,
7182 );
7183 Element? previousChild;
7184 for (int i = 0; i < children.length; i += 1) {
7185 final Element newChild = inflateWidget(
7186 multiChildRenderObjectWidget.children[i],
7187 IndexedSlot<Element?>(i, previousChild),
7188 );
7189 children[i] = newChild;
7190 previousChild = newChild;
7191 }
7192 _children = children;
7193 }
7194
7195 @override
7196 void update(MultiChildRenderObjectWidget newWidget) {
7197 super.update(newWidget);
7198 final MultiChildRenderObjectWidget multiChildRenderObjectWidget =
7199 widget as MultiChildRenderObjectWidget;
7200 assert(widget == newWidget);
7201 assert(!debugChildrenHaveDuplicateKeys(widget, multiChildRenderObjectWidget.children));
7202 _children = updateChildren(
7203 _children,
7204 multiChildRenderObjectWidget.children,
7205 forgottenChildren: _forgottenChildren,
7206 );
7207 _forgottenChildren.clear();
7208 }
7209}
7210
7211/// A [RenderObjectElement] used to manage the root of a render tree.
7212///
7213/// Unlike any other render object element this element does not attempt to
7214/// attach its [renderObject] to the closest ancestor [RenderObjectElement].
7215/// Instead, subclasses must override [attachRenderObject] and
7216/// [detachRenderObject] to attach/detach the [renderObject] to whatever
7217/// instance manages the render tree (e.g. by assigning it to
7218/// [PipelineOwner.rootNode]).
7219abstract class RenderTreeRootElement extends RenderObjectElement {
7220 /// Creates an element that uses the given widget as its configuration.
7221 RenderTreeRootElement(super.widget);
7222
7223 @override
7224 @mustCallSuper
7225 void attachRenderObject(Object? newSlot) {
7226 _slot = newSlot;
7227 assert(_debugCheckMustNotAttachRenderObjectToAncestor());
7228 }
7229
7230 @override
7231 @mustCallSuper
7232 void detachRenderObject() {
7233 _slot = null;
7234 }
7235
7236 @override
7237 void updateSlot(Object? newSlot) {
7238 super.updateSlot(newSlot);
7239 assert(_debugCheckMustNotAttachRenderObjectToAncestor());
7240 }
7241
7242 bool _debugCheckMustNotAttachRenderObjectToAncestor() {
7243 if (!kDebugMode) {
7244 return true;
7245 }
7246 if (_findAncestorRenderObjectElement() != null) {
7247 throw FlutterError.fromParts(<DiagnosticsNode>[
7248 ErrorSummary(
7249 'The RenderObject for ${toStringShort()} cannot maintain an independent render tree at its current location.',
7250 ),
7251 ErrorDescription(
7252 'The ownership chain for the RenderObject in question was:\n ${debugGetCreatorChain(10)}',
7253 ),
7254 ErrorDescription(
7255 'This RenderObject is the root of an independent render tree and it cannot '
7256 'attach itself to an ancestor in an existing tree. The ancestor RenderObject, '
7257 'however, expects that a child will be attached.',
7258 ),
7259 ErrorHint(
7260 'Try moving the subtree that contains the ${toStringShort()} widget '
7261 'to a location where it is not expected to attach its RenderObject '
7262 'to a parent. This could mean moving the subtree into the view '
7263 'property of a "ViewAnchor" widget or - if the subtree is the root of '
7264 'your widget tree - passing it to "runWidget" instead of "runApp".',
7265 ),
7266 ErrorHint(
7267 'If you are seeing this error in a test and the subtree containing '
7268 'the ${toStringShort()} widget is passed to "WidgetTester.pumpWidget", '
7269 'consider setting the "wrapWithView" parameter of that method to false.',
7270 ),
7271 ]);
7272 }
7273 return true;
7274 }
7275}
7276
7277/// A wrapper class for the [Element] that is the creator of a [RenderObject].
7278///
7279/// Setting a [DebugCreator] as [RenderObject.debugCreator] will lead to better
7280/// error messages.
7281class DebugCreator {
7282 /// Create a [DebugCreator] instance with input [Element].
7283 DebugCreator(this.element);
7284
7285 /// The creator of the [RenderObject].
7286 final Element element;
7287
7288 @override
7289 String toString() => element.debugGetCreatorChain(12);
7290}
7291
7292FlutterErrorDetails _reportException(
7293 DiagnosticsNode context,
7294 Object exception,
7295 StackTrace? stack, {
7296 InformationCollector? informationCollector,
7297}) {
7298 final FlutterErrorDetails details = FlutterErrorDetails(
7299 exception: exception,
7300 stack: stack,
7301 library: 'widgets library',
7302 context: context,
7303 informationCollector: informationCollector,
7304 );
7305 FlutterError.reportError(details);
7306 return details;
7307}
7308
7309/// A value for [Element.slot] used for children of
7310/// [MultiChildRenderObjectElement]s.
7311///
7312/// A slot for a [MultiChildRenderObjectElement] consists of an [index]
7313/// identifying where the child occupying this slot is located in the
7314/// [MultiChildRenderObjectElement]'s child list and an arbitrary [value] that
7315/// can further define where the child occupying this slot fits in its
7316/// parent's child list.
7317///
7318/// See also:
7319///
7320/// * [RenderObjectElement.updateChildren], which discusses why this class is
7321/// used as slot values for the children of a [MultiChildRenderObjectElement].
7322@immutable
7323class IndexedSlot<T extends Element?> {
7324 /// Creates an [IndexedSlot] with the provided [index] and slot [value].
7325 const IndexedSlot(this.index, this.value);
7326
7327 /// Information to define where the child occupying this slot fits in its
7328 /// parent's child list.
7329 final T value;
7330
7331 /// The index of this slot in the parent's child list.
7332 final int index;
7333
7334 @override
7335 bool operator ==(Object other) {
7336 if (other.runtimeType != runtimeType) {
7337 return false;
7338 }
7339 return other is IndexedSlot && index == other.index && value == other.value;
7340 }
7341
7342 @override
7343 int get hashCode => Object.hash(index, value);
7344}
7345
7346/// Used as a placeholder in [List<Element>] objects when the actual
7347/// elements are not yet determined.
7348class _NullElement extends Element {
7349 _NullElement() : super(const _NullWidget());
7350
7351 static _NullElement instance = _NullElement();
7352
7353 @override
7354 bool get debugDoingBuild => throw UnimplementedError();
7355}
7356
7357class _NullWidget extends Widget {
7358 const _NullWidget();
7359
7360 @override
7361 Element createElement() => throw UnimplementedError();
7362}
7363