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
5import 'dart:async';
6import 'dart:collection';
7
8import 'package:flutter/foundation.dart';
9import 'package:flutter/rendering.dart';
10
11import 'binding.dart';
12import 'debug.dart';
13import 'focus_manager.dart';
14import 'inherited_model.dart';
15import 'notification_listener.dart';
16import 'widget_inspector.dart';
17
18export 'package:flutter/foundation.dart' show
19 factory,
20 immutable,
21 mustCallSuper,
22 optionalTypeArgs,
23 protected,
24 required,
25 visibleForTesting;
26export 'package:flutter/foundation.dart' show ErrorDescription, ErrorHint, ErrorSummary, FlutterError, debugPrint, debugPrintStack;
27export 'package:flutter/foundation.dart' show ValueChanged, ValueGetter, ValueSetter, VoidCallback;
28export 'package:flutter/foundation.dart' show DiagnosticLevel, DiagnosticsNode;
29export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;
30export 'package:flutter/rendering.dart' show RenderBox, RenderObject, debugDumpLayerTree, debugDumpRenderTree;
31
32// Examples can assume:
33// late BuildContext context;
34// void setState(VoidCallback fn) { }
35// abstract class RenderFrogJar extends RenderObject { }
36// abstract class FrogJar extends RenderObjectWidget { const FrogJar({super.key}); }
37// abstract class FrogJarParentData extends ParentData { late Size size; }
38// abstract class SomeWidget extends StatefulWidget { const SomeWidget({super.key}); }
39// typedef ChildWidget = Placeholder;
40// class _SomeWidgetState extends State { @override Widget build(BuildContext context) => widget; }
41// abstract class RenderFoo extends RenderObject { }
42// abstract class Foo extends RenderObjectWidget { const Foo({super.key}); }
43// abstract class StatefulWidgetX { const StatefulWidgetX({this.key}); final Key? key; Widget build(BuildContext context, State state); }
44// class SpecialWidget extends StatelessWidget { const SpecialWidget({ super.key, this.handler }); final VoidCallback? handler; @override Widget build(BuildContext context) => this; }
45// late Object? _myState, newValue;
46// int _counter = 0;
47// Future getApplicationDocumentsDirectory() async => Directory('');
48// late AnimationController animation;
49
50// An annotation used by test_analysis package to verify patterns are followed
51// that allow for tree-shaking of both fields and their initializers. This
52// annotation has no impact on code by itself, but indicates the following pattern
53// should be followed for a given field:
54//
55// ```dart
56// class Foo {
57// final bar = kDebugMode ? Object() : null;
58// }
59// ```
60class _DebugOnly {
61 const _DebugOnly();
62}
63
64const _DebugOnly _debugOnly = _DebugOnly();
65
66// KEYS
67
68/// A key that takes its identity from the object used as its value.
69///
70/// Used to tie the identity of a widget to the identity of an object used to
71/// generate that widget.
72///
73/// See also:
74///
75/// * [Key], the base class for all keys.
76/// * The discussion at [Widget.key] for more information about how widgets use
77/// keys.
78class ObjectKey extends LocalKey {
79 /// Creates a key that uses [identical] on [value] for its [operator==].
80 const ObjectKey(this.value);
81
82 /// The object whose identity is used by this key's [operator==].
83 final Object? value;
84
85 @override
86 bool operator ==(Object other) {
87 if (other.runtimeType != runtimeType) {
88 return false;
89 }
90 return other is ObjectKey
91 && identical(other.value, value);
92 }
93
94 @override
95 int get hashCode => Object.hash(runtimeType, identityHashCode(value));
96
97 @override
98 String toString() {
99 if (runtimeType == ObjectKey) {
100 return '[${describeIdentity(value)}]';
101 }
102 return '[${objectRuntimeType(this, 'ObjectKey')} ${describeIdentity(value)}]';
103 }
104}
105
106/// A key that is unique across the entire app.
107///
108/// Global keys uniquely identify elements. Global keys provide access to other
109/// objects that are associated with those elements, such as [BuildContext].
110/// For [StatefulWidget]s, global keys also provide access to [State].
111///
112/// Widgets that have global keys reparent their subtrees when they are moved
113/// from one location in the tree to another location in the tree. In order to
114/// reparent its subtree, a widget must arrive at its new location in the tree
115/// in the same animation frame in which it was removed from its old location in
116/// the tree.
117///
118/// Reparenting an [Element] using a global key is relatively expensive, as
119/// this operation will trigger a call to [State.deactivate] on the associated
120/// [State] and all of its descendants; then force all widgets that depends
121/// on an [InheritedWidget] to rebuild.
122///
123/// If you don't need any of the features listed above, consider using a [Key],
124/// [ValueKey], [ObjectKey], or [UniqueKey] instead.
125///
126/// You cannot simultaneously include two widgets in the tree with the same
127/// global key. Attempting to do so will assert at runtime.
128///
129/// ## Pitfalls
130///
131/// GlobalKeys should not be re-created on every build. They should usually be
132/// long-lived objects owned by a [State] object, for example.
133///
134/// Creating a new GlobalKey on every build will throw away the state of the
135/// subtree associated with the old key and create a new fresh subtree for the
136/// new key. Besides harming performance, this can also cause unexpected
137/// behavior in widgets in the subtree. For example, a [GestureDetector] in the
138/// subtree will be unable to track ongoing gestures since it will be recreated
139/// on each build.
140///
141/// Instead, a good practice is to let a State object own the GlobalKey, and
142/// instantiate it outside the build method, such as in [State.initState].
143///
144/// See also:
145///
146/// * The discussion at [Widget.key] for more information about how widgets use
147/// keys.
148@optionalTypeArgs
149abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
150 /// Creates a [LabeledGlobalKey], which is a [GlobalKey] with a label used for
151 /// debugging.
152 ///
153 /// The label is purely for debugging and not used for comparing the identity
154 /// of the key.
155 factory GlobalKey({ String? debugLabel }) => LabeledGlobalKey<T>(debugLabel);
156
157 /// Creates a global key without a label.
158 ///
159 /// Used by subclasses because the factory constructor shadows the implicit
160 /// constructor.
161 const GlobalKey.constructor() : super.empty();
162
163 Element? get _currentElement => WidgetsBinding.instance.buildOwner!._globalKeyRegistry[this];
164
165 /// The build context in which the widget with this key builds.
166 ///
167 /// The current context is null if there is no widget in the tree that matches
168 /// this global key.
169 BuildContext? get currentContext => _currentElement;
170
171 /// The widget in the tree that currently has this global key.
172 ///
173 /// The current widget is null if there is no widget in the tree that matches
174 /// this global key.
175 Widget? get currentWidget => _currentElement?.widget;
176
177 /// The [State] for the widget in the tree that currently has this global key.
178 ///
179 /// The current state is null if (1) there is no widget in the tree that
180 /// matches this global key, (2) that widget is not a [StatefulWidget], or the
181 /// associated [State] object is not a subtype of `T`.
182 T? get currentState {
183 final Element? element = _currentElement;
184 if (element is StatefulElement) {
185 final StatefulElement statefulElement = element;
186 final State state = statefulElement.state;
187 if (state is T) {
188 return state;
189 }
190 }
191 return null;
192 }
193}
194
195/// A global key with a debugging label.
196///
197/// The debug label is useful for documentation and for debugging. The label
198/// does not affect the key's identity.
199@optionalTypeArgs
200class LabeledGlobalKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
201 /// Creates a global key with a debugging label.
202 ///
203 /// The label does not affect the key's identity.
204 // ignore: prefer_const_constructors_in_immutables , never use const for this class
205 LabeledGlobalKey(this._debugLabel) : super.constructor();
206
207 final String? _debugLabel;
208
209 @override
210 String toString() {
211 final String label = _debugLabel != null ? ' $_debugLabel' : '';
212 if (runtimeType == LabeledGlobalKey) {
213 return '[GlobalKey#${shortHash(this)}$label]';
214 }
215 return '[${describeIdentity(this)}$label]';
216 }
217}
218
219/// A global key that takes its identity from the object used as its value.
220///
221/// Used to tie the identity of a widget to the identity of an object used to
222/// generate that widget.
223///
224/// Any [GlobalObjectKey] created for the same object will match.
225///
226/// If the object is not private, then it is possible that collisions will occur
227/// where independent widgets will reuse the same object as their
228/// [GlobalObjectKey] value in a different part of the tree, leading to a global
229/// key conflict. To avoid this problem, create a private [GlobalObjectKey]
230/// subclass, as in:
231///
232/// ```dart
233/// class _MyKey extends GlobalObjectKey {
234/// const _MyKey(super.value);
235/// }
236/// ```
237///
238/// Since the [runtimeType] of the key is part of its identity, this will
239/// prevent clashes with other [GlobalObjectKey]s even if they have the same
240/// value.
241@optionalTypeArgs
242class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
243 /// Creates a global key that uses [identical] on [value] for its [operator==].
244 const GlobalObjectKey(this.value) : super.constructor();
245
246 /// The object whose identity is used by this key's [operator==].
247 final Object value;
248
249 @override
250 bool operator ==(Object other) {
251 if (other.runtimeType != runtimeType) {
252 return false;
253 }
254 return other is GlobalObjectKey<T>
255 && identical(other.value, value);
256 }
257
258 @override
259 int get hashCode => identityHashCode(value);
260
261 @override
262 String toString() {
263 String selfType = objectRuntimeType(this, 'GlobalObjectKey');
264 // The runtimeType string of a GlobalObjectKey() returns 'GlobalObjectKey>'
265 // because GlobalObjectKey is instantiated to its bounds. To avoid cluttering the output
266 // we remove the suffix.
267 const String suffix = '<State<StatefulWidget>>';
268 if (selfType.endsWith(suffix)) {
269 selfType = selfType.substring(0, selfType.length - suffix.length);
270 }
271 return '[$selfType ${describeIdentity(value)}]';
272 }
273}
274
275/// Describes the configuration for an [Element].
276///
277/// Widgets are the central class hierarchy in the Flutter framework. A widget
278/// is an immutable description of part of a user interface. Widgets can be
279/// inflated into elements, which manage the underlying render tree.
280///
281/// Widgets themselves have no mutable state (all their fields must be final).
282/// If you wish to associate mutable state with a widget, consider using a
283/// [StatefulWidget], which creates a [State] object (via
284/// [StatefulWidget.createState]) whenever it is inflated into an element and
285/// incorporated into the tree.
286///
287/// A given widget can be included in the tree zero or more times. In particular
288/// a given widget can be placed in the tree multiple times. Each time a widget
289/// is placed in the tree, it is inflated into an [Element], which means a
290/// widget that is incorporated into the tree multiple times will be inflated
291/// multiple times.
292///
293/// The [key] property controls how one widget replaces another widget in the
294/// tree. If the [runtimeType] and [key] properties of the two widgets are
295/// [operator==], respectively, then the new widget replaces the old widget by
296/// updating the underlying element (i.e., by calling [Element.update] with the
297/// new widget). Otherwise, the old element is removed from the tree, the new
298/// widget is inflated into an element, and the new element is inserted into the
299/// tree.
300///
301/// See also:
302///
303/// * [StatefulWidget] and [State], for widgets that can build differently
304/// several times over their lifetime.
305/// * [InheritedWidget], for widgets that introduce ambient state that can
306/// be read by descendant widgets.
307/// * [StatelessWidget], for widgets that always build the same way given a
308/// particular configuration and ambient state.
309@immutable
310abstract class Widget extends DiagnosticableTree {
311 /// Initializes [key] for subclasses.
312 const Widget({ this.key });
313
314 /// Controls how one widget replaces another widget in the tree.
315 ///
316 /// If the [runtimeType] and [key] properties of the two widgets are
317 /// [operator==], respectively, then the new widget replaces the old widget by
318 /// updating the underlying element (i.e., by calling [Element.update] with the
319 /// new widget). Otherwise, the old element is removed from the tree, the new
320 /// widget is inflated into an element, and the new element is inserted into the
321 /// tree.
322 ///
323 /// In addition, using a [GlobalKey] as the widget's [key] allows the element
324 /// to be moved around the tree (changing parent) without losing state. When a
325 /// new widget is found (its key and type do not match a previous widget in
326 /// the same location), but there was a widget with that same global key
327 /// elsewhere in the tree in the previous frame, then that widget's element is
328 /// moved to the new location.
329 ///
330 /// Generally, a widget that is the only child of another widget does not need
331 /// an explicit key.
332 ///
333 /// See also:
334 ///
335 /// * The discussions at [Key] and [GlobalKey].
336 final Key? key;
337
338 /// Inflates this configuration to a concrete instance.
339 ///
340 /// A given widget can be included in the tree zero or more times. In particular
341 /// a given widget can be placed in the tree multiple times. Each time a widget
342 /// is placed in the tree, it is inflated into an [Element], which means a
343 /// widget that is incorporated into the tree multiple times will be inflated
344 /// multiple times.
345 @protected
346 @factory
347 Element createElement();
348
349 /// A short, textual description of this widget.
350 @override
351 String toStringShort() {
352 final String type = objectRuntimeType(this, 'Widget');
353 return key == null ? type : '$type-$key';
354 }
355
356 @override
357 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
358 super.debugFillProperties(properties);
359 properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
360 }
361
362 @override
363 @nonVirtual
364 bool operator ==(Object other) => super == other;
365
366 @override
367 @nonVirtual
368 int get hashCode => super.hashCode;
369
370 /// Whether the `newWidget` can be used to update an [Element] that currently
371 /// has the `oldWidget` as its configuration.
372 ///
373 /// An element that uses a given widget as its configuration can be updated to
374 /// use another widget as its configuration if, and only if, the two widgets
375 /// have [runtimeType] and [key] properties that are [operator==].
376 ///
377 /// If the widgets have no key (their key is null), then they are considered a
378 /// match if they have the same type, even if their children are completely
379 /// different.
380 static bool canUpdate(Widget oldWidget, Widget newWidget) {
381 return oldWidget.runtimeType == newWidget.runtimeType
382 && oldWidget.key == newWidget.key;
383 }
384
385 // Return a numeric encoding of the specific `Widget` concrete subtype.
386 // This is used in `Element.updateChild` to determine if a hot reload modified the
387 // superclass of a mounted element's configuration. The encoding of each `Widget`
388 // must match the corresponding `Element` encoding in `Element._debugConcreteSubtype`.
389 static int _debugConcreteSubtype(Widget widget) {
390 return widget is StatefulWidget ? 1 :
391 widget is StatelessWidget ? 2 :
392 0;
393 }
394}
395
396/// A widget that does not require mutable state.
397///
398/// A stateless widget is a widget that describes part of the user interface by
399/// building a constellation of other widgets that describe the user interface
400/// more concretely. The building process continues recursively until the
401/// description of the user interface is fully concrete (e.g., consists
402/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
403///
404/// {@youtube 560 315 https://www.youtube.com/watch?v=wE7khGHVkYY}
405///
406/// Stateless widget are useful when the part of the user interface you are
407/// describing does not depend on anything other than the configuration
408/// information in the object itself and the [BuildContext] in which the widget
409/// is inflated. For compositions that can change dynamically, e.g. due to
410/// having an internal clock-driven state, or depending on some system state,
411/// consider using [StatefulWidget].
412///
413/// ## Performance considerations
414///
415/// The [build] method of a stateless widget is typically only called in three
416/// situations: the first time the widget is inserted in the tree, when the
417/// widget's parent changes its configuration (see [Element.rebuild]), and when
418/// an [InheritedWidget] it depends on changes.
419///
420/// If a widget's parent will regularly change the widget's configuration, or if
421/// it depends on inherited widgets that frequently change, then it is important
422/// to optimize the performance of the [build] method to maintain a fluid
423/// rendering performance.
424///
425/// There are several techniques one can use to minimize the impact of
426/// rebuilding a stateless widget:
427///
428/// * Minimize the number of nodes transitively created by the build method and
429/// any widgets it creates. For example, instead of an elaborate arrangement
430/// of [Row]s, [Column]s, [Padding]s, and [SizedBox]es to position a single
431/// child in a particularly fancy manner, consider using just an [Align] or a
432/// [CustomSingleChildLayout]. Instead of an intricate layering of multiple
433/// [Container]s and with [Decoration]s to draw just the right graphical
434/// effect, consider a single [CustomPaint] widget.
435///
436/// * Use `const` widgets where possible, and provide a `const` constructor for
437/// the widget so that users of the widget can also do so.
438///
439/// * Consider refactoring the stateless widget into a stateful widget so that
440/// it can use some of the techniques described at [StatefulWidget], such as
441/// caching common parts of subtrees and using [GlobalKey]s when changing the
442/// tree structure.
443///
444/// * If the widget is likely to get rebuilt frequently due to the use of
445/// [InheritedWidget]s, consider refactoring the stateless widget into
446/// multiple widgets, with the parts of the tree that change being pushed to
447/// the leaves. For example instead of building a tree with four widgets, the
448/// inner-most widget depending on the [Theme], consider factoring out the
449/// part of the build function that builds the inner-most widget into its own
450/// widget, so that only the inner-most widget needs to be rebuilt when the
451/// theme changes.
452/// {@template flutter.flutter.widgets.framework.prefer_const_over_helper}
453/// * When trying to create a reusable piece of UI, prefer using a widget
454/// rather than a helper method. For example, if there was a function used to
455/// build a widget, a [State.setState] call would require Flutter to entirely
456/// rebuild the returned wrapping widget. If a [Widget] was used instead,
457/// Flutter would be able to efficiently re-render only those parts that
458/// really need to be updated. Even better, if the created widget is `const`,
459/// Flutter would short-circuit most of the rebuild work.
460/// {@endtemplate}
461///
462/// This video gives more explanations on why `const` constructors are important
463/// and why a [Widget] is better than a helper method.
464///
465/// {@youtube 560 315 https://www.youtube.com/watch?v=IOyq-eTRhvo}
466///
467/// {@tool snippet}
468///
469/// The following is a skeleton of a stateless widget subclass called `GreenFrog`.
470///
471/// Normally, widgets have more constructor arguments, each of which corresponds
472/// to a `final` property.
473///
474/// ```dart
475/// class GreenFrog extends StatelessWidget {
476/// const GreenFrog({ super.key });
477///
478/// @override
479/// Widget build(BuildContext context) {
480/// return Container(color: const Color(0xFF2DBD3A));
481/// }
482/// }
483/// ```
484/// {@end-tool}
485///
486/// {@tool snippet}
487///
488/// This next example shows the more generic widget `Frog` which can be given
489/// a color and a child:
490///
491/// ```dart
492/// class Frog extends StatelessWidget {
493/// const Frog({
494/// super.key,
495/// this.color = const Color(0xFF2DBD3A),
496/// this.child,
497/// });
498///
499/// final Color color;
500/// final Widget? child;
501///
502/// @override
503/// Widget build(BuildContext context) {
504/// return ColoredBox(color: color, child: child);
505/// }
506/// }
507/// ```
508/// {@end-tool}
509///
510/// By convention, widget constructors only use named arguments. Also by
511/// convention, the first argument is [key], and the last argument is `child`,
512/// `children`, or the equivalent.
513///
514/// See also:
515///
516/// * [StatefulWidget] and [State], for widgets that can build differently
517/// several times over their lifetime.
518/// * [InheritedWidget], for widgets that introduce ambient state that can
519/// be read by descendant widgets.
520abstract class StatelessWidget extends Widget {
521 /// Initializes [key] for subclasses.
522 const StatelessWidget({ super.key });
523
524 /// Creates a [StatelessElement] to manage this widget's location in the tree.
525 ///
526 /// It is uncommon for subclasses to override this method.
527 @override
528 StatelessElement createElement() => StatelessElement(this);
529
530 /// Describes the part of the user interface represented by this widget.
531 ///
532 /// The framework calls this method when this widget is inserted into the tree
533 /// in a given [BuildContext] and when the dependencies of this widget change
534 /// (e.g., an [InheritedWidget] referenced by this widget changes). This
535 /// method can potentially be called in every frame and should not have any side
536 /// effects beyond building a widget.
537 ///
538 /// The framework replaces the subtree below this widget with the widget
539 /// returned by this method, either by updating the existing subtree or by
540 /// removing the subtree and inflating a new subtree, depending on whether the
541 /// widget returned by this method can update the root of the existing
542 /// subtree, as determined by calling [Widget.canUpdate].
543 ///
544 /// Typically implementations return a newly created constellation of widgets
545 /// that are configured with information from this widget's constructor and
546 /// from the given [BuildContext].
547 ///
548 /// The given [BuildContext] contains information about the location in the
549 /// tree at which this widget is being built. For example, the context
550 /// provides the set of inherited widgets for this location in the tree. A
551 /// given widget might be built with multiple different [BuildContext]
552 /// arguments over time if the widget is moved around the tree or if the
553 /// widget is inserted into the tree in multiple places at once.
554 ///
555 /// The implementation of this method must only depend on:
556 ///
557 /// * the fields of the widget, which themselves must not change over time,
558 /// and
559 /// * any ambient state obtained from the `context` using
560 /// [BuildContext.dependOnInheritedWidgetOfExactType].
561 ///
562 /// If a widget's [build] method is to depend on anything else, use a
563 /// [StatefulWidget] instead.
564 ///
565 /// See also:
566 ///
567 /// * [StatelessWidget], which contains the discussion on performance considerations.
568 @protected
569 Widget build(BuildContext context);
570}
571
572/// A widget that has mutable state.
573///
574/// State is information that (1) can be read synchronously when the widget is
575/// built and (2) might change during the lifetime of the widget. It is the
576/// responsibility of the widget implementer to ensure that the [State] is
577/// promptly notified when such state changes, using [State.setState].
578///
579/// A stateful widget is a widget that describes part of the user interface by
580/// building a constellation of other widgets that describe the user interface
581/// more concretely. The building process continues recursively until the
582/// description of the user interface is fully concrete (e.g., consists
583/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
584///
585/// Stateful widgets are useful when the part of the user interface you are
586/// describing can change dynamically, e.g. due to having an internal
587/// clock-driven state, or depending on some system state. For compositions that
588/// depend only on the configuration information in the object itself and the
589/// [BuildContext] in which the widget is inflated, consider using
590/// [StatelessWidget].
591///
592/// {@youtube 560 315 https://www.youtube.com/watch?v=AqCMFXEmf3w}
593///
594/// [StatefulWidget] instances themselves are immutable and store their mutable
595/// state either in separate [State] objects that are created by the
596/// [createState] method, or in objects to which that [State] subscribes, for
597/// example [Stream] or [ChangeNotifier] objects, to which references are stored
598/// in final fields on the [StatefulWidget] itself.
599///
600/// The framework calls [createState] whenever it inflates a
601/// [StatefulWidget], which means that multiple [State] objects might be
602/// associated with the same [StatefulWidget] if that widget has been inserted
603/// into the tree in multiple places. Similarly, if a [StatefulWidget] is
604/// removed from the tree and later inserted in to the tree again, the framework
605/// will call [createState] again to create a fresh [State] object, simplifying
606/// the lifecycle of [State] objects.
607///
608/// A [StatefulWidget] keeps the same [State] object when moving from one
609/// location in the tree to another if its creator used a [GlobalKey] for its
610/// [key]. Because a widget with a [GlobalKey] can be used in at most one
611/// location in the tree, a widget that uses a [GlobalKey] has at most one
612/// associated element. The framework takes advantage of this property when
613/// moving a widget with a global key from one location in the tree to another
614/// by grafting the (unique) subtree associated with that widget from the old
615/// location to the new location (instead of recreating the subtree at the new
616/// location). The [State] objects associated with [StatefulWidget] are grafted
617/// along with the rest of the subtree, which means the [State] object is reused
618/// (instead of being recreated) in the new location. However, in order to be
619/// eligible for grafting, the widget must be inserted into the new location in
620/// the same animation frame in which it was removed from the old location.
621///
622/// ## Performance considerations
623///
624/// There are two primary categories of [StatefulWidget]s.
625///
626/// The first is one which allocates resources in [State.initState] and disposes
627/// of them in [State.dispose], but which does not depend on [InheritedWidget]s
628/// or call [State.setState]. Such widgets are commonly used at the root of an
629/// application or page, and communicate with subwidgets via [ChangeNotifier]s,
630/// [Stream]s, or other such objects. Stateful widgets following such a pattern
631/// are relatively cheap (in terms of CPU and GPU cycles), because they are
632/// built once then never update. They can, therefore, have somewhat complicated
633/// and deep build methods.
634///
635/// The second category is widgets that use [State.setState] or depend on
636/// [InheritedWidget]s. These will typically rebuild many times during the
637/// application's lifetime, and it is therefore important to minimize the impact
638/// of rebuilding such a widget. (They may also use [State.initState] or
639/// [State.didChangeDependencies] and allocate resources, but the important part
640/// is that they rebuild.)
641///
642/// There are several techniques one can use to minimize the impact of
643/// rebuilding a stateful widget:
644///
645/// * Push the state to the leaves. For example, if your page has a ticking
646/// clock, rather than putting the state at the top of the page and
647/// rebuilding the entire page each time the clock ticks, create a dedicated
648/// clock widget that only updates itself.
649///
650/// * Minimize the number of nodes transitively created by the build method and
651/// any widgets it creates. Ideally, a stateful widget would only create a
652/// single widget, and that widget would be a [RenderObjectWidget].
653/// (Obviously this isn't always practical, but the closer a widget gets to
654/// this ideal, the more efficient it will be.)
655///
656/// * If a subtree does not change, cache the widget that represents that
657/// subtree and re-use it each time it can be used. To do this, assign
658/// a widget to a `final` state variable and re-use it in the build method. It
659/// is massively more efficient for a widget to be re-used than for a new (but
660/// identically-configured) widget to be created. Another caching strategy
661/// consists in extracting the mutable part of the widget into a [StatefulWidget]
662/// which accepts a child parameter.
663///
664/// * Use `const` widgets where possible. (This is equivalent to caching a
665/// widget and re-using it.)
666///
667/// * Avoid changing the depth of any created subtrees or changing the type of
668/// any widgets in the subtree. For example, rather than returning either the
669/// child or the child wrapped in an [IgnorePointer], always wrap the child
670/// widget in an [IgnorePointer] and control the [IgnorePointer.ignoring]
671/// property. This is because changing the depth of the subtree requires
672/// rebuilding, laying out, and painting the entire subtree, whereas just
673/// changing the property will require the least possible change to the
674/// render tree (in the case of [IgnorePointer], for example, no layout or
675/// repaint is necessary at all).
676///
677/// * If the depth must be changed for some reason, consider wrapping the
678/// common parts of the subtrees in widgets that have a [GlobalKey] that
679/// remains consistent for the life of the stateful widget. (The
680/// [KeyedSubtree] widget may be useful for this purpose if no other widget
681/// can conveniently be assigned the key.)
682///
683/// {@macro flutter.flutter.widgets.framework.prefer_const_over_helper}
684///
685/// This video gives more explanations on why `const` constructors are important
686/// and why a [Widget] is better than a helper method.
687///
688/// {@youtube 560 315 https://www.youtube.com/watch?v=IOyq-eTRhvo}
689///
690/// For more details on the mechanics of rebuilding a widget, see
691/// the discussion at [Element.rebuild].
692///
693/// {@tool snippet}
694///
695/// This is a skeleton of a stateful widget subclass called `YellowBird`.
696///
697/// In this example, the [State] has no actual state. State is normally
698/// represented as private member fields. Also, normally widgets have more
699/// constructor arguments, each of which corresponds to a `final` property.
700///
701/// ```dart
702/// class YellowBird extends StatefulWidget {
703/// const YellowBird({ super.key });
704///
705/// @override
706/// State<YellowBird> createState() => _YellowBirdState();
707/// }
708///
709/// class _YellowBirdState extends State<YellowBird> {
710/// @override
711/// Widget build(BuildContext context) {
712/// return Container(color: const Color(0xFFFFE306));
713/// }
714/// }
715/// ```
716/// {@end-tool}
717/// {@tool snippet}
718///
719/// This example shows the more generic widget `Bird` which can be given a
720/// color and a child, and which has some internal state with a method that
721/// can be called to mutate it:
722///
723/// ```dart
724/// class Bird extends StatefulWidget {
725/// const Bird({
726/// super.key,
727/// this.color = const Color(0xFFFFE306),
728/// this.child,
729/// });
730///
731/// final Color color;
732/// final Widget? child;
733///
734/// @override
735/// State<Bird> createState() => _BirdState();
736/// }
737///
738/// class _BirdState extends State<Bird> {
739/// double _size = 1.0;
740///
741/// void grow() {
742/// setState(() { _size += 0.1; });
743/// }
744///
745/// @override
746/// Widget build(BuildContext context) {
747/// return Container(
748/// color: widget.color,
749/// transform: Matrix4.diagonal3Values(_size, _size, 1.0),
750/// child: widget.child,
751/// );
752/// }
753/// }
754/// ```
755/// {@end-tool}
756///
757/// By convention, widget constructors only use named arguments. Also by
758/// convention, the first argument is [key], and the last argument is `child`,
759/// `children`, or the equivalent.
760///
761/// See also:
762///
763/// * [State], where the logic behind a [StatefulWidget] is hosted.
764/// * [StatelessWidget], for widgets that always build the same way given a
765/// particular configuration and ambient state.
766/// * [InheritedWidget], for widgets that introduce ambient state that can
767/// be read by descendant widgets.
768abstract class StatefulWidget extends Widget {
769 /// Initializes [key] for subclasses.
770 const StatefulWidget({ super.key });
771
772 /// Creates a [StatefulElement] to manage this widget's location in the tree.
773 ///
774 /// It is uncommon for subclasses to override this method.
775 @override
776 StatefulElement createElement() => StatefulElement(this);
777
778 /// Creates the mutable state for this widget at a given location in the tree.
779 ///
780 /// Subclasses should override this method to return a newly created
781 /// instance of their associated [State] subclass:
782 ///
783 /// ```dart
784 /// @override
785 /// State<SomeWidget> createState() => _SomeWidgetState();
786 /// ```
787 ///
788 /// The framework can call this method multiple times over the lifetime of
789 /// a [StatefulWidget]. For example, if the widget is inserted into the tree
790 /// in multiple locations, the framework will create a separate [State] object
791 /// for each location. Similarly, if the widget is removed from the tree and
792 /// later inserted into the tree again, the framework will call [createState]
793 /// again to create a fresh [State] object, simplifying the lifecycle of
794 /// [State] objects.
795 @protected
796 @factory
797 State createState();
798}
799
800/// Tracks the lifecycle of [State] objects when asserts are enabled.
801enum _StateLifecycle {
802 /// The [State] object has been created. [State.initState] is called at this
803 /// time.
804 created,
805
806 /// The [State.initState] method has been called but the [State] object is
807 /// not yet ready to build. [State.didChangeDependencies] is called at this time.
808 initialized,
809
810 /// The [State] object is ready to build and [State.dispose] has not yet been
811 /// called.
812 ready,
813
814 /// The [State.dispose] method has been called and the [State] object is
815 /// no longer able to build.
816 defunct,
817}
818
819/// The signature of [State.setState] functions.
820typedef StateSetter = void Function(VoidCallback fn);
821
822const String _flutterWidgetsLibrary = 'package:flutter/widgets.dart';
823
824/// The logic and internal state for a [StatefulWidget].
825///
826/// State is information that (1) can be read synchronously when the widget is
827/// built and (2) might change during the lifetime of the widget. It is the
828/// responsibility of the widget implementer to ensure that the [State] is
829/// promptly notified when such state changes, using [State.setState].
830///
831/// [State] objects are created by the framework by calling the
832/// [StatefulWidget.createState] method when inflating a [StatefulWidget] to
833/// insert it into the tree. Because a given [StatefulWidget] instance can be
834/// inflated multiple times (e.g., the widget is incorporated into the tree in
835/// multiple places at once), there might be more than one [State] object
836/// associated with a given [StatefulWidget] instance. Similarly, if a
837/// [StatefulWidget] is removed from the tree and later inserted in to the tree
838/// again, the framework will call [StatefulWidget.createState] again to create
839/// a fresh [State] object, simplifying the lifecycle of [State] objects.
840///
841/// [State] objects have the following lifecycle:
842///
843/// * The framework creates a [State] object by calling
844/// [StatefulWidget.createState].
845/// * The newly created [State] object is associated with a [BuildContext].
846/// This association is permanent: the [State] object will never change its
847/// [BuildContext]. However, the [BuildContext] itself can be moved around
848/// the tree along with its subtree. At this point, the [State] object is
849/// considered [mounted].
850/// * The framework calls [initState]. Subclasses of [State] should override
851/// [initState] to perform one-time initialization that depends on the
852/// [BuildContext] or the widget, which are available as the [context] and
853/// [widget] properties, respectively, when the [initState] method is
854/// called.
855/// * The framework calls [didChangeDependencies]. Subclasses of [State] should
856/// override [didChangeDependencies] to perform initialization involving
857/// [InheritedWidget]s. If [BuildContext.dependOnInheritedWidgetOfExactType] is
858/// called, the [didChangeDependencies] method will be called again if the
859/// inherited widgets subsequently change or if the widget moves in the tree.
860/// * At this point, the [State] object is fully initialized and the framework
861/// might call its [build] method any number of times to obtain a
862/// description of the user interface for this subtree. [State] objects can
863/// spontaneously request to rebuild their subtree by calling their
864/// [setState] method, which indicates that some of their internal state
865/// has changed in a way that might impact the user interface in this
866/// subtree.
867/// * During this time, a parent widget might rebuild and request that this
868/// location in the tree update to display a new widget with the same
869/// [runtimeType] and [Widget.key]. When this happens, the framework will
870/// update the [widget] property to refer to the new widget and then call the
871/// [didUpdateWidget] method with the previous widget as an argument. [State]
872/// objects should override [didUpdateWidget] to respond to changes in their
873/// associated widget (e.g., to start implicit animations). The framework
874/// always calls [build] after calling [didUpdateWidget], which means any
875/// calls to [setState] in [didUpdateWidget] are redundant. (See alse the
876/// discussion at [Element.rebuild].)
877/// * During development, if a hot reload occurs (whether initiated from the
878/// command line `flutter` tool by pressing `r`, or from an IDE), the
879/// [reassemble] method is called. This provides an opportunity to
880/// reinitialize any data that was prepared in the [initState] method.
881/// * If the subtree containing the [State] object is removed from the tree
882/// (e.g., because the parent built a widget with a different [runtimeType]
883/// or [Widget.key]), the framework calls the [deactivate] method. Subclasses
884/// should override this method to clean up any links between this object
885/// and other elements in the tree (e.g. if you have provided an ancestor
886/// with a pointer to a descendant's [RenderObject]).
887/// * At this point, the framework might reinsert this subtree into another
888/// part of the tree. If that happens, the framework will ensure that it
889/// calls [build] to give the [State] object a chance to adapt to its new
890/// location in the tree. If the framework does reinsert this subtree, it
891/// will do so before the end of the animation frame in which the subtree was
892/// removed from the tree. For this reason, [State] objects can defer
893/// releasing most resources until the framework calls their [dispose]
894/// method.
895/// * If the framework does not reinsert this subtree by the end of the current
896/// animation frame, the framework will call [dispose], which indicates that
897/// this [State] object will never build again. Subclasses should override
898/// this method to release any resources retained by this object (e.g.,
899/// stop any active animations).
900/// * After the framework calls [dispose], the [State] object is considered
901/// unmounted and the [mounted] property is false. It is an error to call
902/// [setState] at this point. This stage of the lifecycle is terminal: there
903/// is no way to remount a [State] object that has been disposed.
904///
905/// See also:
906///
907/// * [StatefulWidget], where the current configuration of a [State] is hosted,
908/// and whose documentation has sample code for [State].
909/// * [StatelessWidget], for widgets that always build the same way given a
910/// particular configuration and ambient state.
911/// * [InheritedWidget], for widgets that introduce ambient state that can
912/// be read by descendant widgets.
913/// * [Widget], for an overview of widgets in general.
914@optionalTypeArgs
915abstract class State<T extends StatefulWidget> with Diagnosticable {
916 /// The current configuration.
917 ///
918 /// A [State] object's configuration is the corresponding [StatefulWidget]
919 /// instance. This property is initialized by the framework before calling
920 /// [initState]. If the parent updates this location in the tree to a new
921 /// widget with the same [runtimeType] and [Widget.key] as the current
922 /// configuration, the framework will update this property to refer to the new
923 /// widget and then call [didUpdateWidget], passing the old configuration as
924 /// an argument.
925 T get widget => _widget!;
926 T? _widget;
927
928 /// The current stage in the lifecycle for this state object.
929 ///
930 /// This field is used by the framework when asserts are enabled to verify
931 /// that [State] objects move through their lifecycle in an orderly fashion.
932 _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
933
934 /// Verifies that the [State] that was created is one that expects to be
935 /// created for that particular [Widget].
936 bool _debugTypesAreRight(Widget widget) => widget is T;
937
938 /// The location in the tree where this widget builds.
939 ///
940 /// The framework associates [State] objects with a [BuildContext] after
941 /// creating them with [StatefulWidget.createState] and before calling
942 /// [initState]. The association is permanent: the [State] object will never
943 /// change its [BuildContext]. However, the [BuildContext] itself can be moved
944 /// around the tree.
945 ///
946 /// After calling [dispose], the framework severs the [State] object's
947 /// connection with the [BuildContext].
948 BuildContext get context {
949 assert(() {
950 if (_element == null) {
951 throw FlutterError(
952 'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
953 'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
954 );
955 }
956 return true;
957 }());
958 return _element!;
959 }
960 StatefulElement? _element;
961
962 /// Whether this [State] object is currently in a tree.
963 ///
964 /// After creating a [State] object and before calling [initState], the
965 /// framework "mounts" the [State] object by associating it with a
966 /// [BuildContext]. The [State] object remains mounted until the framework
967 /// calls [dispose], after which time the framework will never ask the [State]
968 /// object to [build] again.
969 ///
970 /// It is an error to call [setState] unless [mounted] is true.
971 bool get mounted => _element != null;
972
973 /// Called when this object is inserted into the tree.
974 ///
975 /// The framework will call this method exactly once for each [State] object
976 /// it creates.
977 ///
978 /// Override this method to perform initialization that depends on the
979 /// location at which this object was inserted into the tree (i.e., [context])
980 /// or on the widget used to configure this object (i.e., [widget]).
981 ///
982 /// {@template flutter.widgets.State.initState}
983 /// If a [State]'s [build] method depends on an object that can itself
984 /// change state, for example a [ChangeNotifier] or [Stream], or some
985 /// other object to which one can subscribe to receive notifications, then
986 /// be sure to subscribe and unsubscribe properly in [initState],
987 /// [didUpdateWidget], and [dispose]:
988 ///
989 /// * In [initState], subscribe to the object.
990 /// * In [didUpdateWidget] unsubscribe from the old object and subscribe
991 /// to the new one if the updated widget configuration requires
992 /// replacing the object.
993 /// * In [dispose], unsubscribe from the object.
994 ///
995 /// {@endtemplate}
996 ///
997 /// You should not use [BuildContext.dependOnInheritedWidgetOfExactType] from this
998 /// method. However, [didChangeDependencies] will be called immediately
999 /// following this method, and [BuildContext.dependOnInheritedWidgetOfExactType] can
1000 /// be used there.
1001 ///
1002 /// Implementations of this method should start with a call to the inherited
1003 /// method, as in `super.initState()`.
1004 @protected
1005 @mustCallSuper
1006 void initState() {
1007 assert(_debugLifecycleState == _StateLifecycle.created);
1008 if (kFlutterMemoryAllocationsEnabled) {
1009 MemoryAllocations.instance.dispatchObjectCreated(
1010 library: _flutterWidgetsLibrary,
1011 className: '$State',
1012 object: this,
1013 );
1014 }
1015 }
1016
1017 /// Called whenever the widget configuration changes.
1018 ///
1019 /// If the parent widget rebuilds and requests that this location in the tree
1020 /// update to display a new widget with the same [runtimeType] and
1021 /// [Widget.key], the framework will update the [widget] property of this
1022 /// [State] object to refer to the new widget and then call this method
1023 /// with the previous widget as an argument.
1024 ///
1025 /// Override this method to respond when the [widget] changes (e.g., to start
1026 /// implicit animations).
1027 ///
1028 /// The framework always calls [build] after calling [didUpdateWidget], which
1029 /// means any calls to [setState] in [didUpdateWidget] are redundant.
1030 ///
1031 /// {@macro flutter.widgets.State.initState}
1032 ///
1033 /// Implementations of this method should start with a call to the inherited
1034 /// method, as in `super.didUpdateWidget(oldWidget)`.
1035 ///
1036 /// _See the discussion at [Element.rebuild] for more information on when this
1037 /// method is called._
1038 @mustCallSuper
1039 @protected
1040 void didUpdateWidget(covariant T oldWidget) { }
1041
1042 /// {@macro flutter.widgets.Element.reassemble}
1043 ///
1044 /// In addition to this method being invoked, it is guaranteed that the
1045 /// [build] method will be invoked when a reassemble is signaled. Most
1046 /// widgets therefore do not need to do anything in the [reassemble] method.
1047 ///
1048 /// See also:
1049 ///
1050 /// * [Element.reassemble]
1051 /// * [BindingBase.reassembleApplication]
1052 /// * [Image], which uses this to reload images.
1053 @protected
1054 @mustCallSuper
1055 void reassemble() { }
1056
1057 /// Notify the framework that the internal state of this object has changed.
1058 ///
1059 /// Whenever you change the internal state of a [State] object, make the
1060 /// change in a function that you pass to [setState]:
1061 ///
1062 /// ```dart
1063 /// setState(() { _myState = newValue; });
1064 /// ```
1065 ///
1066 /// The provided callback is immediately called synchronously. It must not
1067 /// return a future (the callback cannot be `async`), since then it would be
1068 /// unclear when the state was actually being set.
1069 ///
1070 /// Calling [setState] notifies the framework that the internal state of this
1071 /// object has changed in a way that might impact the user interface in this
1072 /// subtree, which causes the framework to schedule a [build] for this [State]
1073 /// object.
1074 ///
1075 /// If you just change the state directly without calling [setState], the
1076 /// framework might not schedule a [build] and the user interface for this
1077 /// subtree might not be updated to reflect the new state.
1078 ///
1079 /// Generally it is recommended that the [setState] method only be used to
1080 /// wrap the actual changes to the state, not any computation that might be
1081 /// associated with the change. For example, here a value used by the [build]
1082 /// function is incremented, and then the change is written to disk, but only
1083 /// the increment is wrapped in the [setState]:
1084 ///
1085 /// ```dart
1086 /// Future<void> _incrementCounter() async {
1087 /// setState(() {
1088 /// _counter++;
1089 /// });
1090 /// Directory directory = await getApplicationDocumentsDirectory(); // from path_provider package
1091 /// final String dirName = directory.path;
1092 /// await File('$dirName/counter.txt').writeAsString('$_counter');
1093 /// }
1094 /// ```
1095 ///
1096 /// Sometimes, the changed state is in some other object not owned by the
1097 /// widget [State], but the widget nonetheless needs to be updated to react to
1098 /// the new state. This is especially common with [Listenable]s, such as
1099 /// [AnimationController]s.
1100 ///
1101 /// In such cases, it is good practice to leave a comment in the callback
1102 /// passed to [setState] that explains what state changed:
1103 ///
1104 /// ```dart
1105 /// void _update() {
1106 /// setState(() { /* The animation changed. */ });
1107 /// }
1108 /// //...
1109 /// animation.addListener(_update);
1110 /// ```
1111 ///
1112 /// It is an error to call this method after the framework calls [dispose].
1113 /// You can determine whether it is legal to call this method by checking
1114 /// whether the [mounted] property is true. That said, it is better practice
1115 /// to cancel whatever work might trigger the [setState] rather than merely
1116 /// checking for [mounted] before calling [setState], as otherwise CPU cycles
1117 /// will be wasted.
1118 ///
1119 /// ## Design discussion
1120 ///
1121 /// The original version of this API was a method called `markNeedsBuild`, for
1122 /// consistency with [RenderObject.markNeedsLayout],
1123 /// [RenderObject.markNeedsPaint], _et al_.
1124 ///
1125 /// However, early user testing of the Flutter framework revealed that people
1126 /// would call `markNeedsBuild()` much more often than necessary. Essentially,
1127 /// people used it like a good luck charm, any time they weren't sure if they
1128 /// needed to call it, they would call it, just in case.
1129 ///
1130 /// Naturally, this led to performance issues in applications.
1131 ///
1132 /// When the API was changed to take a callback instead, this practice was
1133 /// greatly reduced. One hypothesis is that prompting developers to actually
1134 /// update their state in a callback caused developers to think more carefully
1135 /// about what exactly was being updated, and thus improved their understanding
1136 /// of the appropriate times to call the method.
1137 ///
1138 /// In practice, the [setState] method's implementation is trivial: it calls
1139 /// the provided callback synchronously, then calls [Element.markNeedsBuild].
1140 ///
1141 /// ## Performance considerations
1142 ///
1143 /// There is minimal _direct_ overhead to calling this function, and as it is
1144 /// expected to be called at most once per frame, the overhead is irrelevant
1145 /// anyway. Nonetheless, it is best to avoid calling this function redundantly
1146 /// (e.g. in a tight loop), as it does involve creating a closure and calling
1147 /// it. The method is idempotent, there is no benefit to calling it more than
1148 /// once per [State] per frame.
1149 ///
1150 /// The _indirect_ cost of causing this function, however, is high: it causes
1151 /// the widget to rebuild, possibly triggering rebuilds for the entire subtree
1152 /// rooted at this widget, and further triggering a relayout and repaint of
1153 /// the entire corresponding [RenderObject] subtree.
1154 ///
1155 /// For this reason, this method should only be called when the [build] method
1156 /// will, as a result of whatever state change was detected, change its result
1157 /// meaningfully.
1158 ///
1159 /// See also:
1160 ///
1161 /// * [StatefulWidget], the API documentation for which has a section on
1162 /// performance considerations that are relevant here.
1163 @protected
1164 void setState(VoidCallback fn) {
1165 assert(() {
1166 if (_debugLifecycleState == _StateLifecycle.defunct) {
1167 throw FlutterError.fromParts(<DiagnosticsNode>[
1168 ErrorSummary('setState() called after dispose(): $this'),
1169 ErrorDescription(
1170 'This error happens if you call setState() on a State object for a widget that '
1171 'no longer appears in the widget tree (e.g., whose parent widget no longer '
1172 'includes the widget in its build). This error can occur when code calls '
1173 'setState() from a timer or an animation callback.',
1174 ),
1175 ErrorHint(
1176 'The preferred solution is '
1177 'to cancel the timer or stop listening to the animation in the dispose() '
1178 'callback. Another solution is to check the "mounted" property of this '
1179 'object before calling setState() to ensure the object is still in the '
1180 'tree.',
1181 ),
1182 ErrorHint(
1183 'This error might indicate a memory leak if setState() is being called '
1184 'because another object is retaining a reference to this State object '
1185 'after it has been removed from the tree. To avoid memory leaks, '
1186 'consider breaking the reference to this object during dispose().',
1187 ),
1188 ]);
1189 }
1190 if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
1191 throw FlutterError.fromParts(<DiagnosticsNode>[
1192 ErrorSummary('setState() called in constructor: $this'),
1193 ErrorHint(
1194 'This happens when you call setState() on a State object for a widget that '
1195 "hasn't been inserted into the widget tree yet. It is not necessary to call "
1196 'setState() in the constructor, since the state is already assumed to be dirty '
1197 'when it is initially created.',
1198 ),
1199 ]);
1200 }
1201 return true;
1202 }());
1203 final Object? result = fn() as dynamic;
1204 assert(() {
1205 if (result is Future) {
1206 throw FlutterError.fromParts(<DiagnosticsNode>[
1207 ErrorSummary('setState() callback argument returned a Future.'),
1208 ErrorDescription(
1209 'The setState() method on $this was called with a closure or method that '
1210 'returned a Future. Maybe it is marked as "async".',
1211 ),
1212 ErrorHint(
1213 'Instead of performing asynchronous work inside a call to setState(), first '
1214 'execute the work (without updating the widget state), and then synchronously '
1215 'update the state inside a call to setState().',
1216 ),
1217 ]);
1218 }
1219 // We ignore other types of return values so that you can do things like:
1220 // setState(() => x = 3);
1221 return true;
1222 }());
1223 _element!.markNeedsBuild();
1224 }
1225
1226 /// Called when this object is removed from the tree.
1227 ///
1228 /// The framework calls this method whenever it removes this [State] object
1229 /// from the tree. In some cases, the framework will reinsert the [State]
1230 /// object into another part of the tree (e.g., if the subtree containing this
1231 /// [State] object is grafted from one location in the tree to another due to
1232 /// the use of a [GlobalKey]). If that happens, the framework will call
1233 /// [activate] to give the [State] object a chance to reacquire any resources
1234 /// that it released in [deactivate]. It will then also call [build] to give
1235 /// the [State] object a chance to adapt to its new location in the tree. If
1236 /// the framework does reinsert this subtree, it will do so before the end of
1237 /// the animation frame in which the subtree was removed from the tree. For
1238 /// this reason, [State] objects can defer releasing most resources until the
1239 /// framework calls their [dispose] method.
1240 ///
1241 /// Subclasses should override this method to clean up any links between
1242 /// this object and other elements in the tree (e.g. if you have provided an
1243 /// ancestor with a pointer to a descendant's [RenderObject]).
1244 ///
1245 /// Implementations of this method should end with a call to the inherited
1246 /// method, as in `super.deactivate()`.
1247 ///
1248 /// See also:
1249 ///
1250 /// * [dispose], which is called after [deactivate] if the widget is removed
1251 /// from the tree permanently.
1252 @protected
1253 @mustCallSuper
1254 void deactivate() { }
1255
1256 /// Called when this object is reinserted into the tree after having been
1257 /// removed via [deactivate].
1258 ///
1259 /// In most cases, after a [State] object has been deactivated, it is _not_
1260 /// reinserted into the tree, and its [dispose] method will be called to
1261 /// signal that it is ready to be garbage collected.
1262 ///
1263 /// In some cases, however, after a [State] object has been deactivated, the
1264 /// framework will reinsert it into another part of the tree (e.g., if the
1265 /// subtree containing this [State] object is grafted from one location in
1266 /// the tree to another due to the use of a [GlobalKey]). If that happens,
1267 /// the framework will call [activate] to give the [State] object a chance to
1268 /// reacquire any resources that it released in [deactivate]. It will then
1269 /// also call [build] to give the object a chance to adapt to its new
1270 /// location in the tree. If the framework does reinsert this subtree, it
1271 /// will do so before the end of the animation frame in which the subtree was
1272 /// removed from the tree. For this reason, [State] objects can defer
1273 /// releasing most resources until the framework calls their [dispose] method.
1274 ///
1275 /// The framework does not call this method the first time a [State] object
1276 /// is inserted into the tree. Instead, the framework calls [initState] in
1277 /// that situation.
1278 ///
1279 /// Implementations of this method should start with a call to the inherited
1280 /// method, as in `super.activate()`.
1281 ///
1282 /// See also:
1283 ///
1284 /// * [Element.activate], the corresponding method when an element
1285 /// transitions from the "inactive" to the "active" lifecycle state.
1286 @protected
1287 @mustCallSuper
1288 void activate() { }
1289
1290 /// Called when this object is removed from the tree permanently.
1291 ///
1292 /// The framework calls this method when this [State] object will never
1293 /// build again. After the framework calls [dispose], the [State] object is
1294 /// considered unmounted and the [mounted] property is false. It is an error
1295 /// to call [setState] at this point. This stage of the lifecycle is terminal:
1296 /// there is no way to remount a [State] object that has been disposed.
1297 ///
1298 /// Subclasses should override this method to release any resources retained
1299 /// by this object (e.g., stop any active animations).
1300 ///
1301 /// {@macro flutter.widgets.State.initState}
1302 ///
1303 /// Implementations of this method should end with a call to the inherited
1304 /// method, as in `super.dispose()`.
1305 ///
1306 /// ## Application shutdown
1307 ///
1308 /// This method is _not_ invoked when the application shuts down, because
1309 /// there is no way to predict when that will happen. For example, a user's
1310 /// battery could catch fire, or the user could drop the device into a
1311 /// swimming pool, or the operating system could unilaterally terminate the
1312 /// application process due to memory pressure.
1313 ///
1314 /// Applications are responsible for ensuring that they are well-behaved
1315 /// even in the face of a rapid unscheduled termination.
1316 ///
1317 /// To artificially cause the entire widget tree to be disposed, consider
1318 /// calling [runApp] with a widget such as [SizedBox.shrink].
1319 ///
1320 /// To listen for platform shutdown messages (and other lifecycle changes),
1321 /// consider the [AppLifecycleListener] API.
1322 ///
1323 /// See also:
1324 ///
1325 /// * [deactivate], which is called prior to [dispose].
1326 @protected
1327 @mustCallSuper
1328 void dispose() {
1329 assert(_debugLifecycleState == _StateLifecycle.ready);
1330 assert(() {
1331 _debugLifecycleState = _StateLifecycle.defunct;
1332 return true;
1333 }());
1334 if (kFlutterMemoryAllocationsEnabled) {
1335 MemoryAllocations.instance.dispatchObjectDisposed(object: this);
1336 }
1337 }
1338
1339 /// Describes the part of the user interface represented by this widget.
1340 ///
1341 /// The framework calls this method in a number of different situations. For
1342 /// example:
1343 ///
1344 /// * After calling [initState].
1345 /// * After calling [didUpdateWidget].
1346 /// * After receiving a call to [setState].
1347 /// * After a dependency of this [State] object changes (e.g., an
1348 /// [InheritedWidget] referenced by the previous [build] changes).
1349 /// * After calling [deactivate] and then reinserting the [State] object into
1350 /// the tree at another location.
1351 ///
1352 /// This method can potentially be called in every frame and should not have
1353 /// any side effects beyond building a widget.
1354 ///
1355 /// The framework replaces the subtree below this widget with the widget
1356 /// returned by this method, either by updating the existing subtree or by
1357 /// removing the subtree and inflating a new subtree, depending on whether the
1358 /// widget returned by this method can update the root of the existing
1359 /// subtree, as determined by calling [Widget.canUpdate].
1360 ///
1361 /// Typically implementations return a newly created constellation of widgets
1362 /// that are configured with information from this widget's constructor, the
1363 /// given [BuildContext], and the internal state of this [State] object.
1364 ///
1365 /// The given [BuildContext] contains information about the location in the
1366 /// tree at which this widget is being built. For example, the context
1367 /// provides the set of inherited widgets for this location in the tree. The
1368 /// [BuildContext] argument is always the same as the [context] property of
1369 /// this [State] object and will remain the same for the lifetime of this
1370 /// object. The [BuildContext] argument is provided redundantly here so that
1371 /// this method matches the signature for a [WidgetBuilder].
1372 ///
1373 /// ## Design discussion
1374 ///
1375 /// ### Why is the [build] method on [State], and not [StatefulWidget]?
1376 ///
1377 /// Putting a `Widget build(BuildContext context)` method on [State] rather
1378 /// than putting a `Widget build(BuildContext context, State state)` method
1379 /// on [StatefulWidget] gives developers more flexibility when subclassing
1380 /// [StatefulWidget].
1381 ///
1382 /// For example, [AnimatedWidget] is a subclass of [StatefulWidget] that
1383 /// introduces an abstract `Widget build(BuildContext context)` method for its
1384 /// subclasses to implement. If [StatefulWidget] already had a [build] method
1385 /// that took a [State] argument, [AnimatedWidget] would be forced to provide
1386 /// its [State] object to subclasses even though its [State] object is an
1387 /// internal implementation detail of [AnimatedWidget].
1388 ///
1389 /// Conceptually, [StatelessWidget] could also be implemented as a subclass of
1390 /// [StatefulWidget] in a similar manner. If the [build] method were on
1391 /// [StatefulWidget] rather than [State], that would not be possible anymore.
1392 ///
1393 /// Putting the [build] function on [State] rather than [StatefulWidget] also
1394 /// helps avoid a category of bugs related to closures implicitly capturing
1395 /// `this`. If you defined a closure in a [build] function on a
1396 /// [StatefulWidget], that closure would implicitly capture `this`, which is
1397 /// the current widget instance, and would have the (immutable) fields of that
1398 /// instance in scope:
1399 ///
1400 /// ```dart
1401 /// // (this is not valid Flutter code)
1402 /// class MyButton extends StatefulWidgetX {
1403 /// MyButton({super.key, required this.color});
1404 ///
1405 /// final Color color;
1406 ///
1407 /// @override
1408 /// Widget build(BuildContext context, State state) {
1409 /// return SpecialWidget(
1410 /// handler: () { print('color: $color'); },
1411 /// );
1412 /// }
1413 /// }
1414 /// ```
1415 ///
1416 /// For example, suppose the parent builds `MyButton` with `color` being blue,
1417 /// the `$color` in the print function refers to blue, as expected. Now,
1418 /// suppose the parent rebuilds `MyButton` with green. The closure created by
1419 /// the first build still implicitly refers to the original widget and the
1420 /// `$color` still prints blue even through the widget has been updated to
1421 /// green; should that closure outlive its widget, it would print outdated
1422 /// information.
1423 ///
1424 /// In contrast, with the [build] function on the [State] object, closures
1425 /// created during [build] implicitly capture the [State] instance instead of
1426 /// the widget instance:
1427 ///
1428 /// ```dart
1429 /// class MyButton extends StatefulWidget {
1430 /// const MyButton({super.key, this.color = Colors.teal});
1431 ///
1432 /// final Color color;
1433 /// // ...
1434 /// }
1435 ///
1436 /// class MyButtonState extends State<MyButton> {
1437 /// // ...
1438 /// @override
1439 /// Widget build(BuildContext context) {
1440 /// return SpecialWidget(
1441 /// handler: () { print('color: ${widget.color}'); },
1442 /// );
1443 /// }
1444 /// }
1445 /// ```
1446 ///
1447 /// Now when the parent rebuilds `MyButton` with green, the closure created by
1448 /// the first build still refers to [State] object, which is preserved across
1449 /// rebuilds, but the framework has updated that [State] object's [widget]
1450 /// property to refer to the new `MyButton` instance and `${widget.color}`
1451 /// prints green, as expected.
1452 ///
1453 /// See also:
1454 ///
1455 /// * [StatefulWidget], which contains the discussion on performance considerations.
1456 @protected
1457 Widget build(BuildContext context);
1458
1459 /// Called when a dependency of this [State] object changes.
1460 ///
1461 /// For example, if the previous call to [build] referenced an
1462 /// [InheritedWidget] that later changed, the framework would call this
1463 /// method to notify this object about the change.
1464 ///
1465 /// This method is also called immediately after [initState]. It is safe to
1466 /// call [BuildContext.dependOnInheritedWidgetOfExactType] from this method.
1467 ///
1468 /// Subclasses rarely override this method because the framework always
1469 /// calls [build] after a dependency changes. Some subclasses do override
1470 /// this method because they need to do some expensive work (e.g., network
1471 /// fetches) when their dependencies change, and that work would be too
1472 /// expensive to do for every build.
1473 @protected
1474 @mustCallSuper
1475 void didChangeDependencies() { }
1476
1477 @override
1478 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
1479 super.debugFillProperties(properties);
1480 assert(() {
1481 properties.add(EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));
1482 return true;
1483 }());
1484 properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
1485 properties.add(ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));
1486 }
1487}
1488
1489/// A widget that has a child widget provided to it, instead of building a new
1490/// widget.
1491///
1492/// Useful as a base class for other widgets, such as [InheritedWidget] and
1493/// [ParentDataWidget].
1494///
1495/// See also:
1496///
1497/// * [InheritedWidget], for widgets that introduce ambient state that can
1498/// be read by descendant widgets.
1499/// * [ParentDataWidget], for widgets that populate the
1500/// [RenderObject.parentData] slot of their child's [RenderObject] to
1501/// configure the parent widget's layout.
1502/// * [StatefulWidget] and [State], for widgets that can build differently
1503/// several times over their lifetime.
1504/// * [StatelessWidget], for widgets that always build the same way given a
1505/// particular configuration and ambient state.
1506/// * [Widget], for an overview of widgets in general.
1507abstract class ProxyWidget extends Widget {
1508 /// Creates a widget that has exactly one child widget.
1509 const ProxyWidget({ super.key, required this.child });
1510
1511 /// The widget below this widget in the tree.
1512 ///
1513 /// {@template flutter.widgets.ProxyWidget.child}
1514 /// This widget can only have one child. To lay out multiple children, let this
1515 /// widget's child be a widget such as [Row], [Column], or [Stack], which have a
1516 /// `children` property, and then provide the children to that widget.
1517 /// {@endtemplate}
1518 final Widget child;
1519}
1520
1521/// Base class for widgets that hook [ParentData] information to children of
1522/// [RenderObjectWidget]s.
1523///
1524/// This can be used to provide per-child configuration for
1525/// [RenderObjectWidget]s with more than one child. For example, [Stack] uses
1526/// the [Positioned] parent data widget to position each child.
1527///
1528/// A [ParentDataWidget] is specific to a particular kind of [ParentData]. That
1529/// class is `T`, the [ParentData] type argument.
1530///
1531/// {@tool snippet}
1532///
1533/// This example shows how you would build a [ParentDataWidget] to configure a
1534/// `FrogJar` widget's children by specifying a [Size] for each one.
1535///
1536/// ```dart
1537/// class FrogSize extends ParentDataWidget<FrogJarParentData> {
1538/// const FrogSize({
1539/// super.key,
1540/// required this.size,
1541/// required super.child,
1542/// });
1543///
1544/// final Size size;
1545///
1546/// @override
1547/// void applyParentData(RenderObject renderObject) {
1548/// final FrogJarParentData parentData = renderObject.parentData! as FrogJarParentData;
1549/// if (parentData.size != size) {
1550/// parentData.size = size;
1551/// final RenderFrogJar targetParent = renderObject.parent! as RenderFrogJar;
1552/// targetParent.markNeedsLayout();
1553/// }
1554/// }
1555///
1556/// @override
1557/// Type get debugTypicalAncestorWidgetClass => FrogJar;
1558/// }
1559/// ```
1560/// {@end-tool}
1561///
1562/// See also:
1563///
1564/// * [RenderObject], the superclass for layout algorithms.
1565/// * [RenderObject.parentData], the slot that this class configures.
1566/// * [ParentData], the superclass of the data that will be placed in
1567/// [RenderObject.parentData] slots. The `T` type parameter for
1568/// [ParentDataWidget] is a [ParentData].
1569/// * [RenderObjectWidget], the class for widgets that wrap [RenderObject]s.
1570/// * [StatefulWidget] and [State], for widgets that can build differently
1571/// several times over their lifetime.
1572abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
1573 /// Abstract const constructor. This constructor enables subclasses to provide
1574 /// const constructors so that they can be used in const expressions.
1575 const ParentDataWidget({ super.key, required super.child });
1576
1577 @override
1578 ParentDataElement<T> createElement() => ParentDataElement<T>(this);
1579
1580 /// Checks if this widget can apply its parent data to the provided
1581 /// `renderObject`.
1582 ///
1583 /// The [RenderObject.parentData] of the provided `renderObject` is
1584 /// typically set up by an ancestor [RenderObjectWidget] of the type returned
1585 /// by [debugTypicalAncestorWidgetClass].
1586 ///
1587 /// This is called just before [applyParentData] is invoked with the same
1588 /// [RenderObject] provided to that method.
1589 bool debugIsValidRenderObject(RenderObject renderObject) {
1590 assert(T != dynamic);
1591 assert(T != ParentData);
1592 return renderObject.parentData is T;
1593 }
1594
1595 /// Describes the [RenderObjectWidget] that is typically used to set up the
1596 /// [ParentData] that [applyParentData] will write to.
1597 ///
1598 /// This is only used in error messages to tell users what widget typically
1599 /// wraps this [ParentDataWidget] through
1600 /// [debugTypicalAncestorWidgetDescription].
1601 ///
1602 /// ## Implementations
1603 ///
1604 /// The returned Type should describe a subclass of `RenderObjectWidget`. If
1605 /// more than one Type is supported, use
1606 /// [debugTypicalAncestorWidgetDescription], which typically inserts this
1607 /// value but can be overridden to describe more than one Type.
1608 ///
1609 /// ```dart
1610 /// @override
1611 /// Type get debugTypicalAncestorWidgetClass => FrogJar;
1612 /// ```
1613 ///
1614 /// If the "typical" parent is generic (`Foo<T>`), consider specifying either
1615 /// a typical type argument (e.g. `Foo<int>` if `int` is typically how the
1616 /// type is specialized), or specifying the upper bound (e.g. `Foo<Object?>`).
1617 Type get debugTypicalAncestorWidgetClass;
1618
1619 /// Describes the [RenderObjectWidget] that is typically used to set up the
1620 /// [ParentData] that [applyParentData] will write to.
1621 ///
1622 /// This is only used in error messages to tell users what widget typically
1623 /// wraps this [ParentDataWidget].
1624 ///
1625 /// Returns [debugTypicalAncestorWidgetClass] by default as a String. This can
1626 /// be overridden to describe more than one Type of valid parent.
1627 String get debugTypicalAncestorWidgetDescription => '$debugTypicalAncestorWidgetClass';
1628
1629 Iterable<DiagnosticsNode> _debugDescribeIncorrectParentDataType({
1630 required ParentData? parentData,
1631 RenderObjectWidget? parentDataCreator,
1632 DiagnosticsNode? ownershipChain,
1633 }) {
1634 assert(T != dynamic);
1635 assert(T != ParentData);
1636
1637 final String description = 'The ParentDataWidget $this wants to apply ParentData of type $T to a RenderObject';
1638 return <DiagnosticsNode>[
1639 if (parentData == null)
1640 ErrorDescription(
1641 '$description, which has not been set up to receive any ParentData.',
1642 )
1643 else
1644 ErrorDescription(
1645 '$description, which has been set up to accept ParentData of incompatible type ${parentData.runtimeType}.',
1646 ),
1647 ErrorHint(
1648 'Usually, this means that the $runtimeType widget has the wrong ancestor RenderObjectWidget. '
1649 'Typically, $runtimeType widgets are placed directly inside $debugTypicalAncestorWidgetDescription widgets.',
1650 ),
1651 if (parentDataCreator != null)
1652 ErrorHint(
1653 'The offending $runtimeType is currently placed inside a ${parentDataCreator.runtimeType} widget.',
1654 ),
1655 if (ownershipChain != null)
1656 ErrorDescription(
1657 'The ownership chain for the RenderObject that received the incompatible parent data was:\n $ownershipChain',
1658 ),
1659 ];
1660 }
1661
1662 /// Write the data from this widget into the given render object's parent data.
1663 ///
1664 /// The framework calls this function whenever it detects that the
1665 /// [RenderObject] associated with the [child] has outdated
1666 /// [RenderObject.parentData]. For example, if the render object was recently
1667 /// inserted into the render tree, the render object's parent data might not
1668 /// match the data in this widget.
1669 ///
1670 /// Subclasses are expected to override this function to copy data from their
1671 /// fields into the [RenderObject.parentData] field of the given render
1672 /// object. The render object's parent is guaranteed to have been created by a
1673 /// widget of type `T`, which usually means that this function can assume that
1674 /// the render object's parent data object inherits from a particular class.
1675 ///
1676 /// If this function modifies data that can change the parent's layout or
1677 /// painting, this function is responsible for calling
1678 /// [RenderObject.markNeedsLayout] or [RenderObject.markNeedsPaint] on the
1679 /// parent, as appropriate.
1680 @protected
1681 void applyParentData(RenderObject renderObject);
1682
1683 /// Whether the [ParentDataElement.applyWidgetOutOfTurn] method is allowed
1684 /// with this widget.
1685 ///
1686 /// This should only return true if this widget represents a [ParentData]
1687 /// configuration that will have no impact on the layout or paint phase.
1688 ///
1689 /// See also:
1690 ///
1691 /// * [ParentDataElement.applyWidgetOutOfTurn], which verifies this in debug
1692 /// mode.
1693 @protected
1694 bool debugCanApplyOutOfTurn() => false;
1695}
1696
1697/// Base class for widgets that efficiently propagate information down the tree.
1698///
1699/// {@youtube 560 315 https://www.youtube.com/watch?v=og-vJqLzg2c}
1700///
1701/// To obtain the nearest instance of a particular type of inherited widget from
1702/// a build context, use [BuildContext.dependOnInheritedWidgetOfExactType].
1703///
1704/// Inherited widgets, when referenced in this way, will cause the consumer to
1705/// rebuild when the inherited widget itself changes state.
1706///
1707/// {@youtube 560 315 https://www.youtube.com/watch?v=Zbm3hjPjQMk}
1708///
1709/// {@tool snippet}
1710///
1711/// The following is a skeleton of an inherited widget called `FrogColor`:
1712///
1713/// ```dart
1714/// class FrogColor extends InheritedWidget {
1715/// const FrogColor({
1716/// super.key,
1717/// required this.color,
1718/// required super.child,
1719/// });
1720///
1721/// final Color color;
1722///
1723/// static FrogColor? maybeOf(BuildContext context) {
1724/// return context.dependOnInheritedWidgetOfExactType<FrogColor>();
1725/// }
1726///
1727/// static FrogColor of(BuildContext context) {
1728/// final FrogColor? result = maybeOf(context);
1729/// assert(result != null, 'No FrogColor found in context');
1730/// return result!;
1731/// }
1732///
1733/// @override
1734/// bool updateShouldNotify(FrogColor oldWidget) => color != oldWidget.color;
1735/// }
1736/// ```
1737/// {@end-tool}
1738///
1739/// ## Implementing the `of` and `maybeOf` methods
1740///
1741/// The convention is to provide two static methods, `of` and `maybeOf`, on the
1742/// [InheritedWidget] which call
1743/// [BuildContext.dependOnInheritedWidgetOfExactType]. This allows the class to
1744/// define its own fallback logic in case there isn't a widget in scope.
1745///
1746/// The `of` method typically returns a non-nullable instance and asserts if the
1747/// [InheritedWidget] isn't found, and the `maybeOf` method returns a nullable
1748/// instance, and returns null if the [InheritedWidget] isn't found. The `of`
1749/// method is typically implemented by calling `maybeOf` internally.
1750///
1751/// Sometimes, the `of` and `maybeOf` methods return some data rather than the
1752/// inherited widget itself; for example, in this case it could have returned a
1753/// [Color] instead of the `FrogColor` widget.
1754///
1755/// Occasionally, the inherited widget is an implementation detail of another
1756/// class, and is therefore private. The `of` and `maybeOf` methods in that case
1757/// are typically implemented on the public class instead. For example, [Theme]
1758/// is implemented as a [StatelessWidget] that builds a private inherited
1759/// widget; [Theme.of] looks for that private inherited widget using
1760/// [BuildContext.dependOnInheritedWidgetOfExactType] and then returns the
1761/// [ThemeData] inside it.
1762///
1763/// ## Calling the `of` or `maybeOf` methods
1764///
1765/// When using the `of` or `maybeOf` methods, the `context` must be a descendant
1766/// of the [InheritedWidget], meaning it must be "below" the [InheritedWidget]
1767/// in the tree.
1768///
1769/// {@tool snippet}
1770///
1771/// In this example, the `context` used is the one from the [Builder], which is
1772/// a child of the `FrogColor` widget, so this works.
1773///
1774/// ```dart
1775/// // continuing from previous example...
1776/// class MyPage extends StatelessWidget {
1777/// const MyPage({super.key});
1778///
1779/// @override
1780/// Widget build(BuildContext context) {
1781/// return Scaffold(
1782/// body: FrogColor(
1783/// color: Colors.green,
1784/// child: Builder(
1785/// builder: (BuildContext innerContext) {
1786/// return Text(
1787/// 'Hello Frog',
1788/// style: TextStyle(color: FrogColor.of(innerContext).color),
1789/// );
1790/// },
1791/// ),
1792/// ),
1793/// );
1794/// }
1795/// }
1796/// ```
1797/// {@end-tool}
1798///
1799/// {@tool snippet}
1800///
1801/// In this example, the `context` used is the one from the `MyOtherPage`
1802/// widget, which is a parent of the `FrogColor` widget, so this does not work,
1803/// and will assert when `FrogColor.of` is called.
1804///
1805/// ```dart
1806/// // continuing from previous example...
1807///
1808/// class MyOtherPage extends StatelessWidget {
1809/// const MyOtherPage({super.key});
1810///
1811/// @override
1812/// Widget build(BuildContext context) {
1813/// return Scaffold(
1814/// body: FrogColor(
1815/// color: Colors.green,
1816/// child: Text(
1817/// 'Hello Frog',
1818/// style: TextStyle(color: FrogColor.of(context).color),
1819/// ),
1820/// ),
1821/// );
1822/// }
1823/// }
1824/// ```
1825/// {@end-tool} {@youtube 560 315 https://www.youtube.com/watch?v=1t-8rBCGBYw}
1826///
1827/// See also:
1828///
1829/// * [StatefulWidget] and [State], for widgets that can build differently
1830/// several times over their lifetime.
1831/// * [StatelessWidget], for widgets that always build the same way given a
1832/// particular configuration and ambient state.
1833/// * [Widget], for an overview of widgets in general.
1834/// * [InheritedNotifier], an inherited widget whose value can be a
1835/// [Listenable], and which will notify dependents whenever the value sends
1836/// notifications.
1837/// * [InheritedModel], an inherited widget that allows clients to subscribe to
1838/// changes for subparts of the value.
1839abstract class InheritedWidget extends ProxyWidget {
1840 /// Abstract const constructor. This constructor enables subclasses to provide
1841 /// const constructors so that they can be used in const expressions.
1842 const InheritedWidget({ super.key, required super.child });
1843
1844 @override
1845 InheritedElement createElement() => InheritedElement(this);
1846
1847 /// Whether the framework should notify widgets that inherit from this widget.
1848 ///
1849 /// When this widget is rebuilt, sometimes we need to rebuild the widgets that
1850 /// inherit from this widget but sometimes we do not. For example, if the data
1851 /// held by this widget is the same as the data held by `oldWidget`, then we
1852 /// do not need to rebuild the widgets that inherited the data held by
1853 /// `oldWidget`.
1854 ///
1855 /// The framework distinguishes these cases by calling this function with the
1856 /// widget that previously occupied this location in the tree as an argument.
1857 /// The given widget is guaranteed to have the same [runtimeType] as this
1858 /// object.
1859 @protected
1860 bool updateShouldNotify(covariant InheritedWidget oldWidget);
1861}
1862
1863/// [RenderObjectWidget]s provide the configuration for [RenderObjectElement]s,
1864/// which wrap [RenderObject]s, which provide the actual rendering of the
1865/// application.
1866///
1867/// Usually, rather than subclassing [RenderObjectWidget] directly, render
1868/// object widgets subclass one of:
1869///
1870/// * [LeafRenderObjectWidget], if the widget has no children.
1871/// * [SingleChildRenderObjectElement], if the widget has exactly one child.
1872/// * [MultiChildRenderObjectWidget], if the widget takes a list of children.
1873/// * [SlottedMultiChildRenderObjectWidget], if the widget organizes its
1874/// children in different named slots.
1875///
1876/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1877abstract class RenderObjectWidget extends Widget {
1878 /// Abstract const constructor. This constructor enables subclasses to provide
1879 /// const constructors so that they can be used in const expressions.
1880 const RenderObjectWidget({ super.key });
1881
1882 /// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
1883 @override
1884 @factory
1885 RenderObjectElement createElement();
1886
1887 /// Creates an instance of the [RenderObject] class that this
1888 /// [RenderObjectWidget] represents, using the configuration described by this
1889 /// [RenderObjectWidget].
1890 ///
1891 /// This method should not do anything with the children of the render object.
1892 /// That should instead be handled by the method that overrides
1893 /// [RenderObjectElement.mount] in the object rendered by this object's
1894 /// [createElement] method. See, for example,
1895 /// [SingleChildRenderObjectElement.mount].
1896 @protected
1897 @factory
1898 RenderObject createRenderObject(BuildContext context);
1899
1900 /// Copies the configuration described by this [RenderObjectWidget] to the
1901 /// given [RenderObject], which will be of the same type as returned by this
1902 /// object's [createRenderObject].
1903 ///
1904 /// This method should not do anything to update the children of the render
1905 /// object. That should instead be handled by the method that overrides
1906 /// [RenderObjectElement.update] in the object rendered by this object's
1907 /// [createElement] method. See, for example,
1908 /// [SingleChildRenderObjectElement.update].
1909 @protected
1910 void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
1911
1912 /// A render object previously associated with this widget has been removed
1913 /// from the tree. The given [RenderObject] will be of the same type as
1914 /// returned by this object's [createRenderObject].
1915 @protected
1916 void didUnmountRenderObject(covariant RenderObject renderObject) { }
1917}
1918
1919/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1920/// that have no children.
1921///
1922/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1923abstract class LeafRenderObjectWidget extends RenderObjectWidget {
1924 /// Abstract const constructor. This constructor enables subclasses to provide
1925 /// const constructors so that they can be used in const expressions.
1926 const LeafRenderObjectWidget({ super.key });
1927
1928 @override
1929 LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
1930}
1931
1932/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1933/// that have a single child slot.
1934///
1935/// The render object assigned to this widget should make use of
1936/// [RenderObjectWithChildMixin] to implement a single-child model. The mixin
1937/// exposes a [RenderObjectWithChildMixin.child] property that allows retrieving
1938/// the render object belonging to the [child] widget.
1939///
1940/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1941abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
1942 /// Abstract const constructor. This constructor enables subclasses to provide
1943 /// const constructors so that they can be used in const expressions.
1944 const SingleChildRenderObjectWidget({ super.key, this.child });
1945
1946 /// The widget below this widget in the tree.
1947 ///
1948 /// {@macro flutter.widgets.ProxyWidget.child}
1949 final Widget? child;
1950
1951 @override
1952 SingleChildRenderObjectElement createElement() => SingleChildRenderObjectElement(this);
1953}
1954
1955/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1956/// that have a single list of children. (This superclass only provides the
1957/// storage for that child list, it doesn't actually provide the updating
1958/// logic.)
1959///
1960/// Subclasses must use a [RenderObject] that mixes in
1961/// [ContainerRenderObjectMixin], which provides the necessary functionality to
1962/// visit the children of the container render object (the render object
1963/// belonging to the [children] widgets). Typically, subclasses will use a
1964/// [RenderBox] that mixes in both [ContainerRenderObjectMixin] and
1965/// [RenderBoxContainerDefaultsMixin].
1966///
1967/// Subclasses must implement [createRenderObject] and [updateRenderObject].
1968///
1969/// See also:
1970///
1971/// * [Stack], which uses [MultiChildRenderObjectWidget].
1972/// * [RenderStack], for an example implementation of the associated render
1973/// object.
1974/// * [SlottedMultiChildRenderObjectWidget], which configures a
1975/// [RenderObject] that instead of having a single list of children organizes
1976/// its children in named slots.
1977abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
1978 /// Initializes fields for subclasses.
1979 const MultiChildRenderObjectWidget({ super.key, this.children = const <Widget>[] });
1980
1981 /// The widgets below this widget in the tree.
1982 ///
1983 /// If this list is going to be mutated, it is usually wise to put a [Key] on
1984 /// each of the child widgets, so that the framework can match old
1985 /// configurations to new configurations and maintain the underlying render
1986 /// objects.
1987 ///
1988 /// Also, a [Widget] in Flutter is immutable, so directly modifying the
1989 /// [children] such as `someMultiChildRenderObjectWidget.children.add(...)` or
1990 /// as the example code below will result in incorrect behaviors. Whenever the
1991 /// children list is modified, a new list object should be provided.
1992 ///
1993 /// ```dart
1994 /// // This code is incorrect.
1995 /// class SomeWidgetState extends State<SomeWidget> {
1996 /// final List<Widget> _children = <Widget>[];
1997 ///
1998 /// void someHandler() {
1999 /// setState(() {
2000 /// _children.add(const ChildWidget());
2001 /// });
2002 /// }
2003 ///
2004 /// @override
2005 /// Widget build(BuildContext context) {
2006 /// // Reusing `List _children` here is problematic.
2007 /// return Row(children: _children);
2008 /// }
2009 /// }
2010 /// ```
2011 ///
2012 /// The following code corrects the problem mentioned above.
2013 ///
2014 /// ```dart
2015 /// class SomeWidgetState extends State<SomeWidget> {
2016 /// final List<Widget> _children = <Widget>[];
2017 ///
2018 /// void someHandler() {
2019 /// setState(() {
2020 /// // The key here allows Flutter to reuse the underlying render
2021 /// // objects even if the children list is recreated.
2022 /// _children.add(ChildWidget(key: UniqueKey()));
2023 /// });
2024 /// }
2025 ///
2026 /// @override
2027 /// Widget build(BuildContext context) {
2028 /// // Always create a new list of children as a Widget is immutable.
2029 /// return Row(children: _children.toList());
2030 /// }
2031 /// }
2032 /// ```
2033 final List<Widget> children;
2034
2035 @override
2036 MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
2037}
2038
2039
2040// ELEMENTS
2041
2042enum _ElementLifecycle {
2043 initial,
2044 active,
2045 inactive,
2046 defunct,
2047}
2048
2049class _InactiveElements {
2050 bool _locked = false;
2051 final Set<Element> _elements = HashSet<Element>();
2052
2053 void _unmount(Element element) {
2054 assert(element._lifecycleState == _ElementLifecycle.inactive);
2055 assert(() {
2056 if (debugPrintGlobalKeyedWidgetLifecycle) {
2057 if (element.widget.key is GlobalKey) {
2058 debugPrint('Discarding $element from inactive elements list.');
2059 }
2060 }
2061 return true;
2062 }());
2063 element.visitChildren((Element child) {
2064 assert(child._parent == element);
2065 _unmount(child);
2066 });
2067 element.unmount();
2068 assert(element._lifecycleState == _ElementLifecycle.defunct);
2069 }
2070
2071 void _unmountAll() {
2072 _locked = true;
2073 final List<Element> elements = _elements.toList()..sort(Element._sort);
2074 _elements.clear();
2075 try {
2076 elements.reversed.forEach(_unmount);
2077 } finally {
2078 assert(_elements.isEmpty);
2079 _locked = false;
2080 }
2081 }
2082
2083 static void _deactivateRecursively(Element element) {
2084 assert(element._lifecycleState == _ElementLifecycle.active);
2085 element.deactivate();
2086 assert(element._lifecycleState == _ElementLifecycle.inactive);
2087 element.visitChildren(_deactivateRecursively);
2088 assert(() {
2089 element.debugDeactivated();
2090 return true;
2091 }());
2092 }
2093
2094 void add(Element element) {
2095 assert(!_locked);
2096 assert(!_elements.contains(element));
2097 assert(element._parent == null);
2098 if (element._lifecycleState == _ElementLifecycle.active) {
2099 _deactivateRecursively(element);
2100 }
2101 _elements.add(element);
2102 }
2103
2104 void remove(Element element) {
2105 assert(!_locked);
2106 assert(_elements.contains(element));
2107 assert(element._parent == null);
2108 _elements.remove(element);
2109 assert(element._lifecycleState != _ElementLifecycle.active);
2110 }
2111
2112 bool debugContains(Element element) {
2113 late bool result;
2114 assert(() {
2115 result = _elements.contains(element);
2116 return true;
2117 }());
2118 return result;
2119 }
2120}
2121
2122/// Signature for the callback to [BuildContext.visitChildElements].
2123///
2124/// The argument is the child being visited.
2125///
2126/// It is safe to call `element.visitChildElements` reentrantly within
2127/// this callback.
2128typedef ElementVisitor = void Function(Element element);
2129
2130/// Signature for the callback to [BuildContext.visitAncestorElements].
2131///
2132/// The argument is the ancestor being visited.
2133///
2134/// Return false to stop the walk.
2135typedef ConditionalElementVisitor = bool Function(Element element);
2136
2137/// A handle to the location of a widget in the widget tree.
2138///
2139/// This class presents a set of methods that can be used from
2140/// [StatelessWidget.build] methods and from methods on [State] objects.
2141///
2142/// [BuildContext] objects are passed to [WidgetBuilder] functions (such as
2143/// [StatelessWidget.build]), and are available from the [State.context] member.
2144/// Some static functions (e.g. [showDialog], [Theme.of], and so forth) also
2145/// take build contexts so that they can act on behalf of the calling widget, or
2146/// obtain data specifically for the given context.
2147///
2148/// Each widget has its own [BuildContext], which becomes the parent of the
2149/// widget returned by the [StatelessWidget.build] or [State.build] function.
2150/// (And similarly, the parent of any children for [RenderObjectWidget]s.)
2151///
2152/// In particular, this means that within a build method, the build context of
2153/// the widget of the build method is not the same as the build context of the
2154/// widgets returned by that build method. This can lead to some tricky cases.
2155/// For example, [Theme.of(context)] looks for the nearest enclosing [Theme] of
2156/// the given build context. If a build method for a widget Q includes a [Theme]
2157/// within its returned widget tree, and attempts to use [Theme.of] passing its
2158/// own context, the build method for Q will not find that [Theme] object. It
2159/// will instead find whatever [Theme] was an ancestor to the widget Q. If the
2160/// build context for a subpart of the returned tree is needed, a [Builder]
2161/// widget can be used: the build context passed to the [Builder.builder]
2162/// callback will be that of the [Builder] itself.
2163///
2164/// For example, in the following snippet, the [ScaffoldState.showBottomSheet]
2165/// method is called on the [Scaffold] widget that the build method itself
2166/// creates. If a [Builder] had not been used, and instead the `context`
2167/// argument of the build method itself had been used, no [Scaffold] would have
2168/// been found, and the [Scaffold.of] function would have returned null.
2169///
2170/// ```dart
2171/// @override
2172/// Widget build(BuildContext context) {
2173/// // here, Scaffold.of(context) returns null
2174/// return Scaffold(
2175/// appBar: AppBar(title: const Text('Demo')),
2176/// body: Builder(
2177/// builder: (BuildContext context) {
2178/// return TextButton(
2179/// child: const Text('BUTTON'),
2180/// onPressed: () {
2181/// Scaffold.of(context).showBottomSheet<void>(
2182/// (BuildContext context) {
2183/// return Container(
2184/// alignment: Alignment.center,
2185/// height: 200,
2186/// color: Colors.amber,
2187/// child: Center(
2188/// child: Column(
2189/// mainAxisSize: MainAxisSize.min,
2190/// children: <Widget>[
2191/// const Text('BottomSheet'),
2192/// ElevatedButton(
2193/// child: const Text('Close BottomSheet'),
2194/// onPressed: () {
2195/// Navigator.pop(context);
2196/// },
2197/// )
2198/// ],
2199/// ),
2200/// ),
2201/// );
2202/// },
2203/// );
2204/// },
2205/// );
2206/// },
2207/// )
2208/// );
2209/// }
2210/// ```
2211///
2212/// The [BuildContext] for a particular widget can change location over time as
2213/// the widget is moved around the tree. Because of this, values returned from
2214/// the methods on this class should not be cached beyond the execution of a
2215/// single synchronous function.
2216///
2217/// {@youtube 560 315 https://www.youtube.com/watch?v=rIaaH87z1-g}
2218///
2219/// Avoid storing instances of [BuildContext]s because they may become invalid
2220/// if the widget they are associated with is unmounted from the widget tree.
2221/// {@template flutter.widgets.BuildContext.asynchronous_gap}
2222/// If a [BuildContext] is used across an asynchronous gap (i.e. after performing
2223/// an asynchronous operation), consider checking [mounted] to determine whether
2224/// the context is still valid before interacting with it:
2225///
2226/// ```dart
2227/// @override
2228/// Widget build(BuildContext context) {
2229/// return OutlinedButton(
2230/// onPressed: () async {
2231/// await Future<void>.delayed(const Duration(seconds: 1));
2232/// if (context.mounted) {
2233/// Navigator.of(context).pop();
2234/// }
2235/// },
2236/// child: const Text('Delayed pop'),
2237/// );
2238/// }
2239/// ```
2240/// {@endtemplate}
2241///
2242/// [BuildContext] objects are actually [Element] objects. The [BuildContext]
2243/// interface is used to discourage direct manipulation of [Element] objects.
2244abstract class BuildContext {
2245 /// The current configuration of the [Element] that is this [BuildContext].
2246 Widget get widget;
2247
2248 /// The [BuildOwner] for this context. The [BuildOwner] is in charge of
2249 /// managing the rendering pipeline for this context.
2250 BuildOwner? get owner;
2251
2252 /// Whether the [Widget] this context is associated with is currently
2253 /// mounted in the widget tree.
2254 ///
2255 /// Accessing the properties of the [BuildContext] or calling any methods on
2256 /// it is only valid while mounted is true. If mounted is false, assertions
2257 /// will trigger.
2258 ///
2259 /// Once unmounted, a given [BuildContext] will never become mounted again.
2260 ///
2261 /// {@macro flutter.widgets.BuildContext.asynchronous_gap}
2262 bool get mounted;
2263
2264 /// Whether the [widget] is currently updating the widget or render tree.
2265 ///
2266 /// For [StatefulWidget]s and [StatelessWidget]s this flag is true while
2267 /// their respective build methods are executing.
2268 /// [RenderObjectWidget]s set this to true while creating or configuring their
2269 /// associated [RenderObject]s.
2270 /// Other [Widget] types may set this to true for conceptually similar phases
2271 /// of their lifecycle.
2272 ///
2273 /// When this is true, it is safe for [widget] to establish a dependency to an
2274 /// [InheritedWidget] by calling [dependOnInheritedElement] or
2275 /// [dependOnInheritedWidgetOfExactType].
2276 ///
2277 /// Accessing this flag in release mode is not valid.
2278 bool get debugDoingBuild;
2279
2280 /// The current [RenderObject] for the widget. If the widget is a
2281 /// [RenderObjectWidget], this is the render object that the widget created
2282 /// for itself. Otherwise, it is the render object of the first descendant
2283 /// [RenderObjectWidget].
2284 ///
2285 /// This method will only return a valid result after the build phase is
2286 /// complete. It is therefore not valid to call this from a build method.
2287 /// It should only be called from interaction event handlers (e.g.
2288 /// gesture callbacks) or layout or paint callbacks. It is also not valid to
2289 /// call if [State.mounted] returns false.
2290 ///
2291 /// If the render object is a [RenderBox], which is the common case, then the
2292 /// size of the render object can be obtained from the [size] getter. This is
2293 /// only valid after the layout phase, and should therefore only be examined
2294 /// from paint callbacks or interaction event handlers (e.g. gesture
2295 /// callbacks).
2296 ///
2297 /// For details on the different phases of a frame, see the discussion at
2298 /// [WidgetsBinding.drawFrame].
2299 ///
2300 /// Calling this method is theoretically relatively expensive (O(N) in the
2301 /// depth of the tree), but in practice is usually cheap because the tree
2302 /// usually has many render objects and therefore the distance to the nearest
2303 /// render object is usually short.
2304 RenderObject? findRenderObject();
2305
2306 /// The size of the [RenderBox] returned by [findRenderObject].
2307 ///
2308 /// This getter will only return a valid result after the layout phase is
2309 /// complete. It is therefore not valid to call this from a build method.
2310 /// It should only be called from paint callbacks or interaction event
2311 /// handlers (e.g. gesture callbacks).
2312 ///
2313 /// For details on the different phases of a frame, see the discussion at
2314 /// [WidgetsBinding.drawFrame].
2315 ///
2316 /// This getter will only return a valid result if [findRenderObject] actually
2317 /// returns a [RenderBox]. If [findRenderObject] returns a render object that
2318 /// is not a subtype of [RenderBox] (e.g., [RenderView]), this getter will
2319 /// throw an exception in debug mode and will return null in release mode.
2320 ///
2321 /// Calling this getter is theoretically relatively expensive (O(N) in the
2322 /// depth of the tree), but in practice is usually cheap because the tree
2323 /// usually has many render objects and therefore the distance to the nearest
2324 /// render object is usually short.
2325 Size? get size;
2326
2327 /// Registers this build context with [ancestor] such that when
2328 /// [ancestor]'s widget changes this build context is rebuilt.
2329 ///
2330 /// Returns `ancestor.widget`.
2331 ///
2332 /// This method is rarely called directly. Most applications should use
2333 /// [dependOnInheritedWidgetOfExactType], which calls this method after finding
2334 /// the appropriate [InheritedElement] ancestor.
2335 ///
2336 /// All of the qualifications about when [dependOnInheritedWidgetOfExactType] can
2337 /// be called apply to this method as well.
2338 InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect });
2339
2340 /// Returns the nearest widget of the given type `T` and creates a dependency
2341 /// on it, or null if no appropriate widget is found.
2342 ///
2343 /// The widget found will be a concrete [InheritedWidget] subclass, and
2344 /// calling [dependOnInheritedWidgetOfExactType] registers this build context
2345 /// with the returned widget. When that widget changes (or a new widget of
2346 /// that type is introduced, or the widget goes away), this build context is
2347 /// rebuilt so that it can obtain new values from that widget.
2348 ///
2349 /// {@template flutter.widgets.BuildContext.dependOnInheritedWidgetOfExactType}
2350 /// This is typically called implicitly from `of()` static methods, e.g.
2351 /// [Theme.of].
2352 ///
2353 /// This method should not be called from widget constructors or from
2354 /// [State.initState] methods, because those methods would not get called
2355 /// again if the inherited value were to change. To ensure that the widget
2356 /// correctly updates itself when the inherited value changes, only call this
2357 /// (directly or indirectly) from build methods, layout and paint callbacks,
2358 /// or from [State.didChangeDependencies] (which is called immediately after
2359 /// [State.initState]).
2360 ///
2361 /// This method should not be called from [State.dispose] because the element
2362 /// tree is no longer stable at that time. To refer to an ancestor from that
2363 /// method, save a reference to the ancestor in [State.didChangeDependencies].
2364 /// It is safe to use this method from [State.deactivate], which is called
2365 /// whenever the widget is removed from the tree.
2366 ///
2367 /// It is also possible to call this method from interaction event handlers
2368 /// (e.g. gesture callbacks) or timers, to obtain a value once, as long as
2369 /// that value is not cached and/or reused later.
2370 ///
2371 /// Calling this method is O(1) with a small constant factor, but will lead to
2372 /// the widget being rebuilt more often.
2373 ///
2374 /// Once a widget registers a dependency on a particular type by calling this
2375 /// method, it will be rebuilt, and [State.didChangeDependencies] will be
2376 /// called, whenever changes occur relating to that widget until the next time
2377 /// the widget or one of its ancestors is moved (for example, because an
2378 /// ancestor is added or removed).
2379 ///
2380 /// The [aspect] parameter is only used when `T` is an
2381 /// [InheritedWidget] subclasses that supports partial updates, like
2382 /// [InheritedModel]. It specifies what "aspect" of the inherited
2383 /// widget this context depends on.
2384 /// {@endtemplate}
2385 T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect });
2386
2387 /// Returns the nearest widget of the given [InheritedWidget] subclass `T` or
2388 /// null if an appropriate ancestor is not found.
2389 ///
2390 /// This method does not introduce a dependency the way that the more typical
2391 /// [dependOnInheritedWidgetOfExactType] does, so this context will not be
2392 /// rebuilt if the [InheritedWidget] changes. This function is meant for those
2393 /// uncommon use cases where a dependency is undesirable.
2394 ///
2395 /// This method should not be called from [State.dispose] because the element
2396 /// tree is no longer stable at that time. To refer to an ancestor from that
2397 /// method, save a reference to the ancestor in [State.didChangeDependencies].
2398 /// It is safe to use this method from [State.deactivate], which is called
2399 /// whenever the widget is removed from the tree.
2400 ///
2401 /// It is also possible to call this method from interaction event handlers
2402 /// (e.g. gesture callbacks) or timers, to obtain a value once, as long as
2403 /// that value is not cached and/or reused later.
2404 ///
2405 /// Calling this method is O(1) with a small constant factor.
2406 T? getInheritedWidgetOfExactType<T extends InheritedWidget>();
2407
2408 /// Obtains the element corresponding to the nearest widget of the given type `T`,
2409 /// which must be the type of a concrete [InheritedWidget] subclass.
2410 ///
2411 /// Returns null if no such element is found.
2412 ///
2413 /// {@template flutter.widgets.BuildContext.getElementForInheritedWidgetOfExactType}
2414 /// Calling this method is O(1) with a small constant factor.
2415 ///
2416 /// This method does not establish a relationship with the target in the way
2417 /// that [dependOnInheritedWidgetOfExactType] does.
2418 ///
2419 /// This method should not be called from [State.dispose] because the element
2420 /// tree is no longer stable at that time. To refer to an ancestor from that
2421 /// method, save a reference to the ancestor by calling
2422 /// [dependOnInheritedWidgetOfExactType] in [State.didChangeDependencies]. It is
2423 /// safe to use this method from [State.deactivate], which is called whenever
2424 /// the widget is removed from the tree.
2425 /// {@endtemplate}
2426 InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
2427
2428 /// Returns the nearest ancestor widget of the given type `T`, which must be the
2429 /// type of a concrete [Widget] subclass.
2430 ///
2431 /// {@template flutter.widgets.BuildContext.findAncestorWidgetOfExactType}
2432 /// In general, [dependOnInheritedWidgetOfExactType] is more useful, since
2433 /// inherited widgets will trigger consumers to rebuild when they change. This
2434 /// method is appropriate when used in interaction event handlers (e.g.
2435 /// gesture callbacks) or for performing one-off tasks such as asserting that
2436 /// you have or don't have a widget of a specific type as an ancestor. The
2437 /// return value of a Widget's build method should not depend on the value
2438 /// returned by this method, because the build context will not rebuild if the
2439 /// return value of this method changes. This could lead to a situation where
2440 /// data used in the build method changes, but the widget is not rebuilt.
2441 ///
2442 /// Calling this method is relatively expensive (O(N) in the depth of the
2443 /// tree). Only call this method if the distance from this widget to the
2444 /// desired ancestor is known to be small and bounded.
2445 ///
2446 /// This method should not be called from [State.deactivate] or [State.dispose]
2447 /// because the widget tree is no longer stable at that time. To refer to
2448 /// an ancestor from one of those methods, save a reference to the ancestor
2449 /// by calling [findAncestorWidgetOfExactType] in [State.didChangeDependencies].
2450 ///
2451 /// Returns null if a widget of the requested type does not appear in the
2452 /// ancestors of this context.
2453 /// {@endtemplate}
2454 T? findAncestorWidgetOfExactType<T extends Widget>();
2455
2456 /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
2457 /// that is an instance of the given type `T`.
2458 ///
2459 /// {@template flutter.widgets.BuildContext.findAncestorStateOfType}
2460 /// This should not be used from build methods, because the build context will
2461 /// not be rebuilt if the value that would be returned by this method changes.
2462 /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2463 /// cases. This method is useful for changing the state of an ancestor widget in
2464 /// a one-off manner, for example, to cause an ancestor scrolling list to
2465 /// scroll this build context's widget into view, or to move the focus in
2466 /// response to user interaction.
2467 ///
2468 /// In general, though, consider using a callback that triggers a stateful
2469 /// change in the ancestor rather than using the imperative style implied by
2470 /// this method. This will usually lead to more maintainable and reusable code
2471 /// since it decouples widgets from each other.
2472 ///
2473 /// Calling this method is relatively expensive (O(N) in the depth of the
2474 /// tree). Only call this method if the distance from this widget to the
2475 /// desired ancestor is known to be small and bounded.
2476 ///
2477 /// This method should not be called from [State.deactivate] or [State.dispose]
2478 /// because the widget tree is no longer stable at that time. To refer to
2479 /// an ancestor from one of those methods, save a reference to the ancestor
2480 /// by calling [findAncestorStateOfType] in [State.didChangeDependencies].
2481 /// {@endtemplate}
2482 ///
2483 /// {@tool snippet}
2484 ///
2485 /// ```dart
2486 /// ScrollableState? scrollable = context.findAncestorStateOfType<ScrollableState>();
2487 /// ```
2488 /// {@end-tool}
2489 T? findAncestorStateOfType<T extends State>();
2490
2491 /// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
2492 /// that is an instance of the given type `T`.
2493 ///
2494 /// {@template flutter.widgets.BuildContext.findRootAncestorStateOfType}
2495 /// Functions the same way as [findAncestorStateOfType] but keeps visiting subsequent
2496 /// ancestors until there are none of the type instance of `T` remaining.
2497 /// Then returns the last one found.
2498 ///
2499 /// This operation is O(N) as well though N is the entire widget tree rather than
2500 /// a subtree.
2501 /// {@endtemplate}
2502 T? findRootAncestorStateOfType<T extends State>();
2503
2504 /// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
2505 /// that is an instance of the given type `T`.
2506 ///
2507 /// {@template flutter.widgets.BuildContext.findAncestorRenderObjectOfType}
2508 /// This should not be used from build methods, because the build context will
2509 /// not be rebuilt if the value that would be returned by this method changes.
2510 /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2511 /// cases. This method is useful only in esoteric cases where a widget needs
2512 /// to cause an ancestor to change its layout or paint behavior. For example,
2513 /// it is used by [Material] so that [InkWell] widgets can trigger the ink
2514 /// splash on the [Material]'s actual render object.
2515 ///
2516 /// Calling this method is relatively expensive (O(N) in the depth of the
2517 /// tree). Only call this method if the distance from this widget to the
2518 /// desired ancestor is known to be small and bounded.
2519 ///
2520 /// This method should not be called from [State.deactivate] or [State.dispose]
2521 /// because the widget tree is no longer stable at that time. To refer to
2522 /// an ancestor from one of those methods, save a reference to the ancestor
2523 /// by calling [findAncestorRenderObjectOfType] in [State.didChangeDependencies].
2524 /// {@endtemplate}
2525 T? findAncestorRenderObjectOfType<T extends RenderObject>();
2526
2527 /// Walks the ancestor chain, starting with the parent of this build context's
2528 /// widget, invoking the argument for each ancestor.
2529 ///
2530 /// {@template flutter.widgets.BuildContext.visitAncestorElements}
2531 /// The callback is given a reference to the ancestor widget's corresponding
2532 /// [Element] object. The walk stops when it reaches the root widget or when
2533 /// the callback returns false. The callback must not return null.
2534 ///
2535 /// This is useful for inspecting the widget tree.
2536 ///
2537 /// Calling this method is relatively expensive (O(N) in the depth of the tree).
2538 ///
2539 /// This method should not be called from [State.deactivate] or [State.dispose]
2540 /// because the element tree is no longer stable at that time. To refer to
2541 /// an ancestor from one of those methods, save a reference to the ancestor
2542 /// by calling [visitAncestorElements] in [State.didChangeDependencies].
2543 /// {@endtemplate}
2544 void visitAncestorElements(ConditionalElementVisitor visitor);
2545
2546 /// Walks the children of this widget.
2547 ///
2548 /// {@template flutter.widgets.BuildContext.visitChildElements}
2549 /// This is useful for applying changes to children after they are built
2550 /// without waiting for the next frame, especially if the children are known,
2551 /// and especially if there is exactly one child (as is always the case for
2552 /// [StatefulWidget]s or [StatelessWidget]s).
2553 ///
2554 /// Calling this method is very cheap for build contexts that correspond to
2555 /// [StatefulWidget]s or [StatelessWidget]s (O(1), since there's only one
2556 /// child).
2557 ///
2558 /// Calling this method is potentially expensive for build contexts that
2559 /// correspond to [RenderObjectWidget]s (O(N) in the number of children).
2560 ///
2561 /// Calling this method recursively is extremely expensive (O(N) in the number
2562 /// of descendants), and should be avoided if possible. Generally it is
2563 /// significantly cheaper to use an [InheritedWidget] and have the descendants
2564 /// pull data down, than it is to use [visitChildElements] recursively to push
2565 /// data down to them.
2566 /// {@endtemplate}
2567 void visitChildElements(ElementVisitor visitor);
2568
2569 /// Start bubbling this notification at the given build context.
2570 ///
2571 /// The notification will be delivered to any [NotificationListener] widgets
2572 /// with the appropriate type parameters that are ancestors of the given
2573 /// [BuildContext].
2574 void dispatchNotification(Notification notification);
2575
2576 /// Returns a description of the [Element] associated with the current build context.
2577 ///
2578 /// The `name` is typically something like "The element being rebuilt was".
2579 ///
2580 /// See also:
2581 ///
2582 /// * [Element.describeElements], which can be used to describe a list of elements.
2583 DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});
2584
2585 /// Returns a description of the [Widget] associated with the current build context.
2586 ///
2587 /// The `name` is typically something like "The widget being rebuilt was".
2588 DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});
2589
2590 /// Adds a description of a specific type of widget missing from the current
2591 /// build context's ancestry tree.
2592 ///
2593 /// You can find an example of using this method in [debugCheckHasMaterial].
2594 List<DiagnosticsNode> describeMissingAncestor({ required Type expectedAncestorType });
2595
2596 /// Adds a description of the ownership chain from a specific [Element]
2597 /// to the error report.
2598 ///
2599 /// The ownership chain is useful for debugging the source of an element.
2600 DiagnosticsNode describeOwnershipChain(String name);
2601}
2602
2603/// Manager class for the widgets framework.
2604///
2605/// This class tracks which widgets need rebuilding, and handles other tasks
2606/// that apply to widget trees as a whole, such as managing the inactive element
2607/// list for the tree and triggering the "reassemble" command when necessary
2608/// during hot reload when debugging.
2609///
2610/// The main build owner is typically owned by the [WidgetsBinding], and is
2611/// driven from the operating system along with the rest of the
2612/// build/layout/paint pipeline.
2613///
2614/// Additional build owners can be built to manage off-screen widget trees.
2615///
2616/// To assign a build owner to a tree, use the
2617/// [RootElementMixin.assignOwner] method on the root element of the
2618/// widget tree.
2619///
2620/// {@tool dartpad}
2621/// This example shows how to build an off-screen widget tree used to measure
2622/// the layout size of the rendered tree. For some use cases, the simpler
2623/// [Offstage] widget may be a better alternative to this approach.
2624///
2625/// ** See code in examples/api/lib/widgets/framework/build_owner.0.dart **
2626/// {@end-tool}
2627class BuildOwner {
2628 /// Creates an object that manages widgets.
2629 ///
2630 /// If the `focusManager` argument is not specified or is null, this will
2631 /// construct a new [FocusManager] and register its global input handlers
2632 /// via [FocusManager.registerGlobalHandlers], which will modify static
2633 /// state. Callers wishing to avoid altering this state can explicitly pass
2634 /// a focus manager here.
2635 BuildOwner({ this.onBuildScheduled, FocusManager? focusManager }) :
2636 focusManager = focusManager ?? (FocusManager()..registerGlobalHandlers());
2637
2638 /// Called on each build pass when the first buildable element is marked
2639 /// dirty.
2640 VoidCallback? onBuildScheduled;
2641
2642 final _InactiveElements _inactiveElements = _InactiveElements();
2643
2644 final List<Element> _dirtyElements = <Element>[];
2645 bool _scheduledFlushDirtyElements = false;
2646
2647 /// Whether [_dirtyElements] need to be sorted again as a result of more
2648 /// elements becoming dirty during the build.
2649 ///
2650 /// This is necessary to preserve the sort order defined by [Element._sort].
2651 ///
2652 /// This field is set to null when [buildScope] is not actively rebuilding
2653 /// the widget tree.
2654 bool? _dirtyElementsNeedsResorting;
2655
2656 /// Whether [buildScope] is actively rebuilding the widget tree.
2657 ///
2658 /// [scheduleBuildFor] should only be called when this value is true.
2659 bool get _debugIsInBuildScope => _dirtyElementsNeedsResorting != null;
2660
2661 /// The object in charge of the focus tree.
2662 ///
2663 /// Rarely used directly. Instead, consider using [FocusScope.of] to obtain
2664 /// the [FocusScopeNode] for a given [BuildContext].
2665 ///
2666 /// See [FocusManager] for more details.
2667 ///
2668 /// This field will default to a [FocusManager] that has registered its
2669 /// global input handlers via [FocusManager.registerGlobalHandlers]. Callers
2670 /// wishing to avoid registering those handlers (and modifying the associated
2671 /// static state) can explicitly pass a focus manager to the [BuildOwner.new]
2672 /// constructor.
2673 FocusManager focusManager;
2674
2675 /// Adds an element to the dirty elements list so that it will be rebuilt
2676 /// when [WidgetsBinding.drawFrame] calls [buildScope].
2677 void scheduleBuildFor(Element element) {
2678 assert(element.owner == this);
2679 assert(() {
2680 if (debugPrintScheduleBuildForStacks) {
2681 debugPrintStack(label: 'scheduleBuildFor() called for $element${_dirtyElements.contains(element) ? " (ALREADY IN LIST)" : ""}');
2682 }
2683 if (!element.dirty) {
2684 throw FlutterError.fromParts(<DiagnosticsNode>[
2685 ErrorSummary('scheduleBuildFor() called for a widget that is not marked as dirty.'),
2686 element.describeElement('The method was called for the following element'),
2687 ErrorDescription(
2688 'This element is not current marked as dirty. Make sure to set the dirty flag before '
2689 'calling scheduleBuildFor().',
2690 ),
2691 ErrorHint(
2692 'If you did not attempt to call scheduleBuildFor() yourself, then this probably '
2693 'indicates a bug in the widgets framework. Please report it:\n'
2694 ' https://github.com/flutter/flutter/issues/new?template=2_bug.yml',
2695 ),
2696 ]);
2697 }
2698 return true;
2699 }());
2700 if (element._inDirtyList) {
2701 assert(() {
2702 if (debugPrintScheduleBuildForStacks) {
2703 debugPrintStack(label: 'BuildOwner.scheduleBuildFor() called; _dirtyElementsNeedsResorting was $_dirtyElementsNeedsResorting (now true); dirty list is: $_dirtyElements');
2704 }
2705 if (!_debugIsInBuildScope) {
2706 throw FlutterError.fromParts(<DiagnosticsNode>[
2707 ErrorSummary('BuildOwner.scheduleBuildFor() called inappropriately.'),
2708 ErrorHint(
2709 'The BuildOwner.scheduleBuildFor() method should only be called while the '
2710 'buildScope() method is actively rebuilding the widget tree.',
2711 ),
2712 ]);
2713 }
2714 return true;
2715 }());
2716 _dirtyElementsNeedsResorting = true;
2717 return;
2718 }
2719 if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
2720 _scheduledFlushDirtyElements = true;
2721 onBuildScheduled!();
2722 }
2723 _dirtyElements.add(element);
2724 element._inDirtyList = true;
2725 assert(() {
2726 if (debugPrintScheduleBuildForStacks) {
2727 debugPrint('...dirty list is now: $_dirtyElements');
2728 }
2729 return true;
2730 }());
2731 }
2732
2733 int _debugStateLockLevel = 0;
2734 bool get _debugStateLocked => _debugStateLockLevel > 0;
2735
2736 /// Whether this widget tree is in the build phase.
2737 ///
2738 /// Only valid when asserts are enabled.
2739 bool get debugBuilding => _debugBuilding;
2740 bool _debugBuilding = false;
2741 Element? _debugCurrentBuildTarget;
2742
2743 /// Establishes a scope in which calls to [State.setState] are forbidden, and
2744 /// calls the given `callback`.
2745 ///
2746 /// This mechanism is used to ensure that, for instance, [State.dispose] does
2747 /// not call [State.setState].
2748 void lockState(VoidCallback callback) {
2749 assert(_debugStateLockLevel >= 0);
2750 assert(() {
2751 _debugStateLockLevel += 1;
2752 return true;
2753 }());
2754 try {
2755 callback();
2756 } finally {
2757 assert(() {
2758 _debugStateLockLevel -= 1;
2759 return true;
2760 }());
2761 }
2762 assert(_debugStateLockLevel >= 0);
2763 }
2764
2765 /// Establishes a scope for updating the widget tree, and calls the given
2766 /// `callback`, if any. Then, builds all the elements that were marked as
2767 /// dirty using [scheduleBuildFor], in depth order.
2768 ///
2769 /// This mechanism prevents build methods from transitively requiring other
2770 /// build methods to run, potentially causing infinite loops.
2771 ///
2772 /// The dirty list is processed after `callback` returns, building all the
2773 /// elements that were marked as dirty using [scheduleBuildFor], in depth
2774 /// order. If elements are marked as dirty while this method is running, they
2775 /// must be deeper than the `context` node, and deeper than any
2776 /// previously-built node in this pass.
2777 ///
2778 /// To flush the current dirty list without performing any other work, this
2779 /// function can be called with no callback. This is what the framework does
2780 /// each frame, in [WidgetsBinding.drawFrame].
2781 ///
2782 /// Only one [buildScope] can be active at a time.
2783 ///
2784 /// A [buildScope] implies a [lockState] scope as well.
2785 ///
2786 /// To print a console message every time this method is called, set
2787 /// [debugPrintBuildScope] to true. This is useful when debugging problems
2788 /// involving widgets not getting marked dirty, or getting marked dirty too
2789 /// often.
2790 @pragma('vm:notify-debugger-on-exception')
2791 void buildScope(Element context, [ VoidCallback? callback ]) {
2792 if (callback == null && _dirtyElements.isEmpty) {
2793 return;
2794 }
2795 assert(_debugStateLockLevel >= 0);
2796 assert(!_debugBuilding);
2797 assert(() {
2798 if (debugPrintBuildScope) {
2799 debugPrint('buildScope called with context $context; dirty list is: $_dirtyElements');
2800 }
2801 _debugStateLockLevel += 1;
2802 _debugBuilding = true;
2803 return true;
2804 }());
2805 if (!kReleaseMode) {
2806 Map<String, String>? debugTimelineArguments;
2807 assert(() {
2808 if (debugEnhanceBuildTimelineArguments) {
2809 debugTimelineArguments = <String, String>{
2810 'dirty count': '${_dirtyElements.length}',
2811 'dirty list': '$_dirtyElements',
2812 'lock level': '$_debugStateLockLevel',
2813 'scope context': '$context',
2814 };
2815 }
2816 return true;
2817 }());
2818 FlutterTimeline.startSync(
2819 'BUILD',
2820 arguments: debugTimelineArguments
2821 );
2822 }
2823 try {
2824 _scheduledFlushDirtyElements = true;
2825 if (callback != null) {
2826 assert(_debugStateLocked);
2827 Element? debugPreviousBuildTarget;
2828 assert(() {
2829 debugPreviousBuildTarget = _debugCurrentBuildTarget;
2830 _debugCurrentBuildTarget = context;
2831 return true;
2832 }());
2833 _dirtyElementsNeedsResorting = false;
2834 try {
2835 callback();
2836 } finally {
2837 assert(() {
2838 assert(_debugCurrentBuildTarget == context);
2839 _debugCurrentBuildTarget = debugPreviousBuildTarget;
2840 _debugElementWasRebuilt(context);
2841 return true;
2842 }());
2843 }
2844 }
2845 _dirtyElements.sort(Element._sort);
2846 _dirtyElementsNeedsResorting = false;
2847 int dirtyCount = _dirtyElements.length;
2848 int index = 0;
2849 while (index < dirtyCount) {
2850 final Element element = _dirtyElements[index];
2851 assert(element._inDirtyList);
2852 assert(() {
2853 if (element._lifecycleState == _ElementLifecycle.active && !element._debugIsInScope(context)) {
2854 throw FlutterError.fromParts(<DiagnosticsNode>[
2855 ErrorSummary('Tried to build dirty widget in the wrong build scope.'),
2856 ErrorDescription(
2857 'A widget which was marked as dirty and is still active was scheduled to be built, '
2858 'but the current build scope unexpectedly does not contain that widget.',
2859 ),
2860 ErrorHint(
2861 'Sometimes this is detected when an element is removed from the widget tree, but the '
2862 'element somehow did not get marked as inactive. In that case, it might be caused by '
2863 'an ancestor element failing to implement visitChildren correctly, thus preventing '
2864 'some or all of its descendants from being correctly deactivated.',
2865 ),
2866 DiagnosticsProperty<Element>(
2867 'The root of the build scope was',
2868 context,
2869 style: DiagnosticsTreeStyle.errorProperty,
2870 ),
2871 DiagnosticsProperty<Element>(
2872 'The offending element (which does not appear to be a descendant of the root of the build scope) was',
2873 element,
2874 style: DiagnosticsTreeStyle.errorProperty,
2875 ),
2876 ]);
2877 }
2878 return true;
2879 }());
2880 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(element.widget);
2881 if (isTimelineTracked) {
2882 Map<String, String>? debugTimelineArguments;
2883 assert(() {
2884 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
2885 debugTimelineArguments = element.widget.toDiagnosticsNode().toTimelineArguments();
2886 }
2887 return true;
2888 }());
2889 FlutterTimeline.startSync(
2890 '${element.widget.runtimeType}',
2891 arguments: debugTimelineArguments,
2892 );
2893 }
2894 try {
2895 element.rebuild();
2896 } catch (e, stack) {
2897 _reportException(
2898 ErrorDescription('while rebuilding dirty elements'),
2899 e,
2900 stack,
2901 informationCollector: () => <DiagnosticsNode>[
2902 if (kDebugMode && index < _dirtyElements.length)
2903 DiagnosticsDebugCreator(DebugCreator(element)),
2904 if (index < _dirtyElements.length)
2905 element.describeElement('The element being rebuilt at the time was index $index of $dirtyCount')
2906 else
2907 ErrorHint('The element being rebuilt at the time was index $index of $dirtyCount, but _dirtyElements only had ${_dirtyElements.length} entries. This suggests some confusion in the framework internals.'),
2908 ],
2909 );
2910 }
2911 if (isTimelineTracked) {
2912 FlutterTimeline.finishSync();
2913 }
2914 index += 1;
2915 if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting!) {
2916 _dirtyElements.sort(Element._sort);
2917 _dirtyElementsNeedsResorting = false;
2918 dirtyCount = _dirtyElements.length;
2919 while (index > 0 && _dirtyElements[index - 1].dirty) {
2920 // It is possible for previously dirty but inactive widgets to move right in the list.
2921 // We therefore have to move the index left in the list to account for this.
2922 // We don't know how many could have moved. However, we do know that the only possible
2923 // change to the list is that nodes that were previously to the left of the index have
2924 // now moved to be to the right of the right-most cleaned node, and we do know that
2925 // all the clean nodes were to the left of the index. So we move the index left
2926 // until just after the right-most clean node.
2927 index -= 1;
2928 }
2929 }
2930 }
2931 assert(() {
2932 if (_dirtyElements.any((Element element) => element._lifecycleState == _ElementLifecycle.active && element.dirty)) {
2933 throw FlutterError.fromParts(<DiagnosticsNode>[
2934 ErrorSummary('buildScope missed some dirty elements.'),
2935 ErrorHint('This probably indicates that the dirty list should have been resorted but was not.'),
2936 Element.describeElements('The list of dirty elements at the end of the buildScope call was', _dirtyElements),
2937 ]);
2938 }
2939 return true;
2940 }());
2941 } finally {
2942 for (final Element element in _dirtyElements) {
2943 assert(element._inDirtyList);
2944 element._inDirtyList = false;
2945 }
2946 _dirtyElements.clear();
2947 _scheduledFlushDirtyElements = false;
2948 _dirtyElementsNeedsResorting = null;
2949 if (!kReleaseMode) {
2950 FlutterTimeline.finishSync();
2951 }
2952 assert(_debugBuilding);
2953 assert(() {
2954 _debugBuilding = false;
2955 _debugStateLockLevel -= 1;
2956 if (debugPrintBuildScope) {
2957 debugPrint('buildScope finished');
2958 }
2959 return true;
2960 }());
2961 }
2962 assert(_debugStateLockLevel >= 0);
2963 }
2964
2965 Map<Element, Set<GlobalKey>>? _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans;
2966
2967 void _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(Element node, GlobalKey key) {
2968 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans ??= HashMap<Element, Set<GlobalKey>>();
2969 final Set<GlobalKey> keys = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!
2970 .putIfAbsent(node, () => HashSet<GlobalKey>());
2971 keys.add(key);
2972 }
2973
2974 void _debugElementWasRebuilt(Element node) {
2975 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.remove(node);
2976 }
2977
2978 final Map<GlobalKey, Element> _globalKeyRegistry = <GlobalKey, Element>{};
2979
2980 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
2981 // eliminate unused fields, but not their initializers.
2982 @_debugOnly
2983 final Set<Element>? _debugIllFatedElements = kDebugMode ? HashSet<Element>() : null;
2984
2985 // This map keeps track which child reserves the global key with the parent.
2986 // Parent, child -> global key.
2987 // This provides us a way to remove old reservation while parent rebuilds the
2988 // child in the same slot.
2989 //
2990 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
2991 // eliminate unused fields, but not their initializers.
2992 @_debugOnly
2993 final Map<Element, Map<Element, GlobalKey>>? _debugGlobalKeyReservations = kDebugMode ? <Element, Map<Element, GlobalKey>>{} : null;
2994
2995 /// The number of [GlobalKey] instances that are currently associated with
2996 /// [Element]s that have been built by this build owner.
2997 int get globalKeyCount => _globalKeyRegistry.length;
2998
2999 void _debugRemoveGlobalKeyReservationFor(Element parent, Element child) {
3000 assert(() {
3001 _debugGlobalKeyReservations?[parent]?.remove(child);
3002 return true;
3003 }());
3004 }
3005
3006 void _registerGlobalKey(GlobalKey key, Element element) {
3007 assert(() {
3008 if (_globalKeyRegistry.containsKey(key)) {
3009 final Element oldElement = _globalKeyRegistry[key]!;
3010 assert(element.widget.runtimeType != oldElement.widget.runtimeType);
3011 _debugIllFatedElements?.add(oldElement);
3012 }
3013 return true;
3014 }());
3015 _globalKeyRegistry[key] = element;
3016 }
3017
3018 void _unregisterGlobalKey(GlobalKey key, Element element) {
3019 assert(() {
3020 if (_globalKeyRegistry.containsKey(key) && _globalKeyRegistry[key] != element) {
3021 final Element oldElement = _globalKeyRegistry[key]!;
3022 assert(element.widget.runtimeType != oldElement.widget.runtimeType);
3023 }
3024 return true;
3025 }());
3026 if (_globalKeyRegistry[key] == element) {
3027 _globalKeyRegistry.remove(key);
3028 }
3029 }
3030
3031 void _debugReserveGlobalKeyFor(Element parent, Element child, GlobalKey key) {
3032 assert(() {
3033 _debugGlobalKeyReservations?[parent] ??= <Element, GlobalKey>{};
3034 _debugGlobalKeyReservations?[parent]![child] = key;
3035 return true;
3036 }());
3037 }
3038
3039 void _debugVerifyGlobalKeyReservation() {
3040 assert(() {
3041 final Map<GlobalKey, Element> keyToParent = <GlobalKey, Element>{};
3042 _debugGlobalKeyReservations?.forEach((Element parent, Map<Element, GlobalKey> childToKey) {
3043 // We ignore parent that are unmounted or detached.
3044 if (parent._lifecycleState == _ElementLifecycle.defunct || parent.renderObject?.attached == false) {
3045 return;
3046 }
3047 childToKey.forEach((Element child, GlobalKey key) {
3048 // If parent = null, the node is deactivated by its parent and is
3049 // not re-attached to other part of the tree. We should ignore this
3050 // node.
3051 if (child._parent == null) {
3052 return;
3053 }
3054 // It is possible the same key registers to the same parent twice
3055 // with different children. That is illegal, but it is not in the
3056 // scope of this check. Such error will be detected in
3057 // _debugVerifyIllFatedPopulation or
3058 // _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.
3059 if (keyToParent.containsKey(key) && keyToParent[key] != parent) {
3060 // We have duplication reservations for the same global key.
3061 final Element older = keyToParent[key]!;
3062 final Element newer = parent;
3063 final FlutterError error;
3064 if (older.toString() != newer.toString()) {
3065 error = FlutterError.fromParts(<DiagnosticsNode>[
3066 ErrorSummary('Multiple widgets used the same GlobalKey.'),
3067 ErrorDescription(
3068 'The key $key was used by multiple widgets. The parents of those widgets were:\n'
3069 '- $older\n'
3070 '- $newer\n'
3071 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
3072 ),
3073 ]);
3074 } else {
3075 error = FlutterError.fromParts(<DiagnosticsNode>[
3076 ErrorSummary('Multiple widgets used the same GlobalKey.'),
3077 ErrorDescription(
3078 'The key $key was used by multiple widgets. The parents of those widgets were '
3079 'different widgets that both had the following description:\n'
3080 ' $parent\n'
3081 'A GlobalKey can only be specified on one widget at a time in the widget tree.',
3082 ),
3083 ]);
3084 }
3085 // Fix the tree by removing the duplicated child from one of its
3086 // parents to resolve the duplicated key issue. This allows us to
3087 // tear down the tree during testing without producing additional
3088 // misleading exceptions.
3089 if (child._parent != older) {
3090 older.visitChildren((Element currentChild) {
3091 if (currentChild == child) {
3092 older.forgetChild(child);
3093 }
3094 });
3095 }
3096 if (child._parent != newer) {
3097 newer.visitChildren((Element currentChild) {
3098 if (currentChild == child) {
3099 newer.forgetChild(child);
3100 }
3101 });
3102 }
3103 throw error;
3104 } else {
3105 keyToParent[key] = parent;
3106 }
3107 });
3108 });
3109 _debugGlobalKeyReservations?.clear();
3110 return true;
3111 }());
3112 }
3113
3114 void _debugVerifyIllFatedPopulation() {
3115 assert(() {
3116 Map<GlobalKey, Set<Element>>? duplicates;
3117 for (final Element element in _debugIllFatedElements ?? const <Element>{}) {
3118 if (element._lifecycleState != _ElementLifecycle.defunct) {
3119 assert(element.widget.key != null);
3120 final GlobalKey key = element.widget.key! as GlobalKey;
3121 assert(_globalKeyRegistry.containsKey(key));
3122 duplicates ??= <GlobalKey, Set<Element>>{};
3123 // Uses ordered set to produce consistent error message.
3124 final Set<Element> elements = duplicates.putIfAbsent(key, () => <Element>{});
3125 elements.add(element);
3126 elements.add(_globalKeyRegistry[key]!);
3127 }
3128 }
3129 _debugIllFatedElements?.clear();
3130 if (duplicates != null) {
3131 final List<DiagnosticsNode> information = <DiagnosticsNode>[];
3132 information.add(ErrorSummary('Multiple widgets used the same GlobalKey.'));
3133 for (final GlobalKey key in duplicates.keys) {
3134 final Set<Element> elements = duplicates[key]!;
3135 // TODO(jacobr): this will omit the '- ' before each widget name and
3136 // use the more standard whitespace style instead. Please let me know
3137 // if the '- ' style is a feature we want to maintain and we can add
3138 // another tree style that supports it. I also see '* ' in some places
3139 // so it would be nice to unify and normalize.
3140 information.add(Element.describeElements('The key $key was used by ${elements.length} widgets', elements));
3141 }
3142 information.add(ErrorDescription('A GlobalKey can only be specified on one widget at a time in the widget tree.'));
3143 throw FlutterError.fromParts(information);
3144 }
3145 return true;
3146 }());
3147 }
3148
3149 /// Complete the element build pass by unmounting any elements that are no
3150 /// longer active.
3151 ///
3152 /// This is called by [WidgetsBinding.drawFrame].
3153 ///
3154 /// In debug mode, this also runs some sanity checks, for example checking for
3155 /// duplicate global keys.
3156 ///
3157 /// After the current call stack unwinds, a microtask that notifies listeners
3158 /// about changes to global keys will run.
3159 @pragma('vm:notify-debugger-on-exception')
3160 void finalizeTree() {
3161 if (!kReleaseMode) {
3162 FlutterTimeline.startSync('FINALIZE TREE');
3163 }
3164 try {
3165 lockState(_inactiveElements._unmountAll); // this unregisters the GlobalKeys
3166 assert(() {
3167 try {
3168 _debugVerifyGlobalKeyReservation();
3169 _debugVerifyIllFatedPopulation();
3170 if (_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans != null &&
3171 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.isNotEmpty) {
3172 final Set<GlobalKey> keys = HashSet<GlobalKey>();
3173 for (final Element element in _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.keys) {
3174 if (element._lifecycleState != _ElementLifecycle.defunct) {
3175 keys.addAll(_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans![element]!);
3176 }
3177 }
3178 if (keys.isNotEmpty) {
3179 final Map<String, int> keyStringCount = HashMap<String, int>();
3180 for (final String key in keys.map<String>((GlobalKey key) => key.toString())) {
3181 if (keyStringCount.containsKey(key)) {
3182 keyStringCount.update(key, (int value) => value + 1);
3183 } else {
3184 keyStringCount[key] = 1;
3185 }
3186 }
3187 final List<String> keyLabels = <String>[];
3188 keyStringCount.forEach((String key, int count) {
3189 if (count == 1) {
3190 keyLabels.add(key);
3191 } else {
3192 keyLabels.add('$key ($count different affected keys had this toString representation)');
3193 }
3194 });
3195 final Iterable<Element> elements = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.keys;
3196 final Map<String, int> elementStringCount = HashMap<String, int>();
3197 for (final String element in elements.map<String>((Element element) => element.toString())) {
3198 if (elementStringCount.containsKey(element)) {
3199 elementStringCount.update(element, (int value) => value + 1);
3200 } else {
3201 elementStringCount[element] = 1;
3202 }
3203 }
3204 final List<String> elementLabels = <String>[];
3205 elementStringCount.forEach((String element, int count) {
3206 if (count == 1) {
3207 elementLabels.add(element);
3208 } else {
3209 elementLabels.add('$element ($count different affected elements had this toString representation)');
3210 }
3211 });
3212 assert(keyLabels.isNotEmpty);
3213 final String the = keys.length == 1 ? ' the' : '';
3214 final String s = keys.length == 1 ? '' : 's';
3215 final String were = keys.length == 1 ? 'was' : 'were';
3216 final String their = keys.length == 1 ? 'its' : 'their';
3217 final String respective = elementLabels.length == 1 ? '' : ' respective';
3218 final String those = keys.length == 1 ? 'that' : 'those';
3219 final String s2 = elementLabels.length == 1 ? '' : 's';
3220 final String those2 = elementLabels.length == 1 ? 'that' : 'those';
3221 final String they = elementLabels.length == 1 ? 'it' : 'they';
3222 final String think = elementLabels.length == 1 ? 'thinks' : 'think';
3223 final String are = elementLabels.length == 1 ? 'is' : 'are';
3224 // TODO(jacobr): make this error more structured to better expose which widgets had problems.
3225 throw FlutterError.fromParts(<DiagnosticsNode>[
3226 ErrorSummary('Duplicate GlobalKey$s detected in widget tree.'),
3227 // TODO(jacobr): refactor this code so the elements are clickable
3228 // in GUI debug tools.
3229 ErrorDescription(
3230 'The following GlobalKey$s $were specified multiple times in the widget tree. This will lead to '
3231 'parts of the widget tree being truncated unexpectedly, because the second time a key is seen, '
3232 'the previous instance is moved to the new location. The key$s $were:\n'
3233 '- ${keyLabels.join("\n ")}\n'
3234 'This was determined by noticing that after$the widget$s with the above global key$s $were moved '
3235 'out of $their$respective previous parent$s2, $those2 previous parent$s2 never updated during this frame, meaning '
3236 'that $they either did not update at all or updated before the widget$s $were moved, in either case '
3237 'implying that $they still $think that $they should have a child with $those global key$s.\n'
3238 'The specific parent$s2 that did not update after having one or more children forcibly removed '
3239 'due to GlobalKey reparenting $are:\n'
3240 '- ${elementLabels.join("\n ")}'
3241 '\nA GlobalKey can only be specified on one widget at a time in the widget tree.',
3242 ),
3243 ]);
3244 }
3245 }
3246 } finally {
3247 _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.clear();
3248 }
3249 return true;
3250 }());
3251 } catch (e, stack) {
3252 // Catching the exception directly to avoid activating the ErrorWidget.
3253 // Since the tree is in a broken state, adding the ErrorWidget would
3254 // cause more exceptions.
3255 _reportException(ErrorSummary('while finalizing the widget tree'), e, stack);
3256 } finally {
3257 if (!kReleaseMode) {
3258 FlutterTimeline.finishSync();
3259 }
3260 }
3261 }
3262
3263 /// Cause the entire subtree rooted at the given [Element] to be entirely
3264 /// rebuilt. This is used by development tools when the application code has
3265 /// changed and is being hot-reloaded, to cause the widget tree to pick up any
3266 /// changed implementations.
3267 ///
3268 /// This is expensive and should not be called except during development.
3269 void reassemble(Element root) {
3270 if (!kReleaseMode) {
3271 FlutterTimeline.startSync('Preparing Hot Reload (widgets)');
3272 }
3273 try {
3274 assert(root._parent == null);
3275 assert(root.owner == this);
3276 root.reassemble();
3277 } finally {
3278 if (!kReleaseMode) {
3279 FlutterTimeline.finishSync();
3280 }
3281 }
3282 }
3283}
3284
3285/// Mixin this class to allow receiving [Notification] objects dispatched by
3286/// child elements.
3287///
3288/// See also:
3289/// * [NotificationListener], for a widget that allows consuming notifications.
3290mixin NotifiableElementMixin on Element {
3291 /// Called when a notification of the appropriate type arrives at this
3292 /// location in the tree.
3293 ///
3294 /// Return true to cancel the notification bubbling. Return false to
3295 /// allow the notification to continue to be dispatched to further ancestors.
3296 bool onNotification(Notification notification);
3297
3298 @override
3299 void attachNotificationTree() {
3300 _notificationTree = _NotificationNode(_parent?._notificationTree, this);
3301 }
3302}
3303
3304class _NotificationNode {
3305 _NotificationNode(this.parent, this.current);
3306
3307 NotifiableElementMixin? current;
3308 _NotificationNode? parent;
3309
3310 void dispatchNotification(Notification notification) {
3311 if (current?.onNotification(notification) ?? true) {
3312 return;
3313 }
3314 parent?.dispatchNotification(notification);
3315 }
3316}
3317
3318bool _isProfileBuildsEnabledFor(Widget widget) {
3319 return debugProfileBuildsEnabled ||
3320 (debugProfileBuildsEnabledUserWidgets &&
3321 debugIsWidgetLocalCreation(widget));
3322}
3323
3324/// An instantiation of a [Widget] at a particular location in the tree.
3325///
3326/// Widgets describe how to configure a subtree but the same widget can be used
3327/// to configure multiple subtrees simultaneously because widgets are immutable.
3328/// An [Element] represents the use of a widget to configure a specific location
3329/// in the tree. Over time, the widget associated with a given element can
3330/// change, for example, if the parent widget rebuilds and creates a new widget
3331/// for this location.
3332///
3333/// Elements form a tree. Most elements have a unique child, but some widgets
3334/// (e.g., subclasses of [RenderObjectElement]) can have multiple children.
3335///
3336/// Elements have the following lifecycle:
3337///
3338/// * The framework creates an element by calling [Widget.createElement] on the
3339/// widget that will be used as the element's initial configuration.
3340/// * The framework calls [mount] to add the newly created element to the tree
3341/// at a given slot in a given parent. The [mount] method is responsible for
3342/// inflating any child widgets and calling [attachRenderObject] as
3343/// necessary to attach any associated render objects to the render tree.
3344/// * At this point, the element is considered "active" and might appear on
3345/// screen.
3346/// * At some point, the parent might decide to change the widget used to
3347/// configure this element, for example because the parent rebuilt with new
3348/// state. When this happens, the framework will call [update] with the new
3349/// widget. The new widget will always have the same [runtimeType] and key as
3350/// old widget. If the parent wishes to change the [runtimeType] or key of
3351/// the widget at this location in the tree, it can do so by unmounting this
3352/// element and inflating the new widget at this location.
3353/// * At some point, an ancestor might decide to remove this element (or an
3354/// intermediate ancestor) from the tree, which the ancestor does by calling
3355/// [deactivateChild] on itself. Deactivating the intermediate ancestor will
3356/// remove that element's render object from the render tree and add this
3357/// element to the [owner]'s list of inactive elements, causing the framework
3358/// to call [deactivate] on this element.
3359/// * At this point, the element is considered "inactive" and will not appear
3360/// on screen. An element can remain in the inactive state only until
3361/// the end of the current animation frame. At the end of the animation
3362/// frame, any elements that are still inactive will be unmounted.
3363/// * If the element gets reincorporated into the tree (e.g., because it or one
3364/// of its ancestors has a global key that is reused), the framework will
3365/// remove the element from the [owner]'s list of inactive elements, call
3366/// [activate] on the element, and reattach the element's render object to
3367/// the render tree. (At this point, the element is again considered "active"
3368/// and might appear on screen.)
3369/// * If the element does not get reincorporated into the tree by the end of
3370/// the current animation frame, the framework will call [unmount] on the
3371/// element.
3372/// * At this point, the element is considered "defunct" and will not be
3373/// incorporated into the tree in the future.
3374abstract class Element extends DiagnosticableTree implements BuildContext {
3375 /// Creates an element that uses the given widget as its configuration.
3376 ///
3377 /// Typically called by an override of [Widget.createElement].
3378 Element(Widget widget)
3379 : _widget = widget {
3380 if (kFlutterMemoryAllocationsEnabled) {
3381 MemoryAllocations.instance.dispatchObjectCreated(
3382 library: _flutterWidgetsLibrary,
3383 className: '$Element',
3384 object: this,
3385 );
3386 }
3387 }
3388
3389 Element? _parent;
3390 _NotificationNode? _notificationTree;
3391
3392 /// Compare two widgets for equality.
3393 ///
3394 /// When a widget is rebuilt with another that compares equal according
3395 /// to `operator ==`, it is assumed that the update is redundant and the
3396 /// work to update that branch of the tree is skipped.
3397 ///
3398 /// It is generally discouraged to override `operator ==` on any widget that
3399 /// has children, since a correct implementation would have to defer to the
3400 /// children's equality operator also, and that is an O(N²) operation: each
3401 /// child would need to itself walk all its children, each step of the tree.
3402 ///
3403 /// It is sometimes reasonable for a leaf widget (one with no children) to
3404 /// implement this method, if rebuilding the widget is known to be much more
3405 /// expensive than checking the widgets' parameters for equality and if the
3406 /// widget is expected to often be rebuilt with identical parameters.
3407 ///
3408 /// In general, however, it is more efficient to cache the widgets used
3409 /// in a build method if it is known that they will not change.
3410 @nonVirtual
3411 @override
3412 // ignore: avoid_equals_and_hash_code_on_mutable_classes, hash_and_equals
3413 bool operator ==(Object other) => identical(this, other);
3414
3415 /// Information set by parent to define where this child fits in its parent's
3416 /// child list.
3417 ///
3418 /// A child widget's slot is determined when the parent's [updateChild] method
3419 /// is called to inflate the child widget. See [RenderObjectElement] for more
3420 /// details on slots.
3421 Object? get slot => _slot;
3422 Object? _slot;
3423
3424 /// An integer that is guaranteed to be greater than the parent's, if any.
3425 /// The element at the root of the tree must have a depth greater than 0.
3426 int get depth {
3427 assert(() {
3428 if (_lifecycleState == _ElementLifecycle.initial) {
3429 throw FlutterError('Depth is only available when element has been mounted.');
3430 }
3431 return true;
3432 }());
3433 return _depth;
3434 }
3435 late int _depth;
3436
3437 /// Returns result < 0 when [a] < [b], result == 0 when [a] == [b], result > 0
3438 /// when [a] > [b].
3439 static int _sort(Element a, Element b) {
3440 final int diff = a.depth - b.depth;
3441 // If depths are not equal, return the difference.
3442 if (diff != 0) {
3443 return diff;
3444 }
3445 // If the `dirty` values are not equal, sort with non-dirty elements being
3446 // less than dirty elements.
3447 final bool isBDirty = b.dirty;
3448 if (a.dirty != isBDirty) {
3449 return isBDirty ? -1 : 1;
3450 }
3451 // Otherwise, `depth`s and `dirty`s are equal.
3452 return 0;
3453 }
3454
3455 // Return a numeric encoding of the specific `Element` concrete subtype.
3456 // This is used in `Element.updateChild` to determine if a hot reload modified the
3457 // superclass of a mounted element's configuration. The encoding of each `Element`
3458 // must match the corresponding `Widget` encoding in `Widget._debugConcreteSubtype`.
3459 static int _debugConcreteSubtype(Element element) {
3460 return element is StatefulElement ? 1 :
3461 element is StatelessElement ? 2 :
3462 0;
3463 }
3464
3465 /// The configuration for this element.
3466 ///
3467 /// Avoid overriding this field on [Element] subtypes to provide a more
3468 /// specific widget type (i.e. [StatelessElement] and [StatelessWidget]).
3469 /// Instead, cast at any call sites where the more specific type is required.
3470 /// This avoids significant cast overhead on the getter which is accessed
3471 /// throughout the framework internals during the build phase - and for which
3472 /// the more specific type information is not used.
3473 @override
3474 Widget get widget => _widget!;
3475 Widget? _widget;
3476
3477 @override
3478 bool get mounted => _widget != null;
3479
3480 /// Returns true if the Element is defunct.
3481 ///
3482 /// This getter always returns false in profile and release builds.
3483 /// See the lifecycle documentation for [Element] for additional information.
3484 bool get debugIsDefunct {
3485 bool isDefunct = false;
3486 assert(() {
3487 isDefunct = _lifecycleState == _ElementLifecycle.defunct;
3488 return true;
3489 }());
3490 return isDefunct;
3491 }
3492
3493 /// Returns true if the Element is active.
3494 ///
3495 /// This getter always returns false in profile and release builds.
3496 /// See the lifecycle documentation for [Element] for additional information.
3497 bool get debugIsActive {
3498 bool isActive = false;
3499 assert(() {
3500 isActive = _lifecycleState == _ElementLifecycle.active;
3501 return true;
3502 }());
3503 return isActive;
3504 }
3505
3506 /// The object that manages the lifecycle of this element.
3507 @override
3508 BuildOwner? get owner => _owner;
3509 BuildOwner? _owner;
3510
3511 /// {@template flutter.widgets.Element.reassemble}
3512 /// Called whenever the application is reassembled during debugging, for
3513 /// example during hot reload.
3514 ///
3515 /// This method should rerun any initialization logic that depends on global
3516 /// state, for example, image loading from asset bundles (since the asset
3517 /// bundle may have changed).
3518 ///
3519 /// This function will only be called during development. In release builds,
3520 /// the `ext.flutter.reassemble` hook is not available, and so this code will
3521 /// never execute.
3522 ///
3523 /// Implementers should not rely on any ordering for hot reload source update,
3524 /// reassemble, and build methods after a hot reload has been initiated. It is
3525 /// possible that a [Timer] (e.g. an [Animation]) or a debugging session
3526 /// attached to the isolate could trigger a build with reloaded code _before_
3527 /// reassemble is called. Code that expects preconditions to be set by
3528 /// reassemble after a hot reload must be resilient to being called out of
3529 /// order, e.g. by fizzling instead of throwing. That said, once reassemble is
3530 /// called, build will be called after it at least once.
3531 /// {@endtemplate}
3532 ///
3533 /// See also:
3534 ///
3535 /// * [State.reassemble]
3536 /// * [BindingBase.reassembleApplication]
3537 /// * [Image], which uses this to reload images.
3538 @mustCallSuper
3539 @protected
3540 void reassemble() {
3541 markNeedsBuild();
3542 visitChildren((Element child) {
3543 child.reassemble();
3544 });
3545 }
3546
3547 bool _debugIsInScope(Element target) {
3548 Element? current = this;
3549 while (current != null) {
3550 if (target == current) {
3551 return true;
3552 }
3553 current = current._parent;
3554 }
3555 return false;
3556 }
3557
3558 /// The render object at (or below) this location in the tree.
3559 ///
3560 /// If this object is a [RenderObjectElement], the render object is the one at
3561 /// this location in the tree. Otherwise, this getter will walk down the tree
3562 /// until it finds a [RenderObjectElement].
3563 ///
3564 /// Some locations in the tree are not backed by a render object. In those
3565 /// cases, this getter returns null. This can happen, if the element is
3566 /// located outside of a [View] since only the element subtree rooted in a
3567 /// view has a render tree associated with it.
3568 RenderObject? get renderObject {
3569 Element? current = this;
3570 while (current != null) {
3571 if (current._lifecycleState == _ElementLifecycle.defunct) {
3572 break;
3573 } else if (current is RenderObjectElement) {
3574 return current.renderObject;
3575 } else {
3576 current = current.renderObjectAttachingChild;
3577 }
3578 }
3579 return null;
3580 }
3581
3582 /// Returns the child of this [Element] that will insert a [RenderObject] into
3583 /// an ancestor of this Element to construct the render tree.
3584 ///
3585 /// Returns null if this Element doesn't have any children who need to attach
3586 /// a [RenderObject] to an ancestor of this [Element]. A [RenderObjectElement]
3587 /// will therefore return null because its children insert their
3588 /// [RenderObject]s into the [RenderObjectElement] itself and not into an
3589 /// ancestor of the [RenderObjectElement].
3590 ///
3591 /// Furthermore, this may return null for [Element]s that hoist their own
3592 /// independent render tree and do not extend the ancestor render tree.
3593 @protected
3594 Element? get renderObjectAttachingChild {
3595 Element? next;
3596 visitChildren((Element child) {
3597 assert(next == null); // This verifies that there's only one child.
3598 next = child;
3599 });
3600 return next;
3601 }
3602
3603 @override
3604 List<DiagnosticsNode> describeMissingAncestor({ required Type expectedAncestorType }) {
3605 final List<DiagnosticsNode> information = <DiagnosticsNode>[];
3606 final List<Element> ancestors = <Element>[];
3607 visitAncestorElements((Element element) {
3608 ancestors.add(element);
3609 return true;
3610 });
3611
3612 information.add(DiagnosticsProperty<Element>(
3613 'The specific widget that could not find a $expectedAncestorType ancestor was',
3614 this,
3615 style: DiagnosticsTreeStyle.errorProperty,
3616 ));
3617
3618 if (ancestors.isNotEmpty) {
3619 information.add(describeElements('The ancestors of this widget were', ancestors));
3620 } else {
3621 information.add(ErrorDescription(
3622 'This widget is the root of the tree, so it has no '
3623 'ancestors, let alone a "$expectedAncestorType" ancestor.',
3624 ));
3625 }
3626 return information;
3627 }
3628
3629 /// Returns a list of [Element]s from the current build context to the error report.
3630 static DiagnosticsNode describeElements(String name, Iterable<Element> elements) {
3631 return DiagnosticsBlock(
3632 name: name,
3633 children: elements.map<DiagnosticsNode>((Element element) => DiagnosticsProperty<Element>('', element)).toList(),
3634 allowTruncate: true,
3635 );
3636 }
3637
3638 @override
3639 DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) {
3640 return DiagnosticsProperty<Element>(name, this, style: style);
3641 }
3642
3643 @override
3644 DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) {
3645 return DiagnosticsProperty<Element>(name, this, style: style);
3646 }
3647
3648 @override
3649 DiagnosticsNode describeOwnershipChain(String name) {
3650 // TODO(jacobr): make this structured so clients can support clicks on
3651 // individual entries. For example, is this an iterable with arrows as
3652 // separators?
3653 return StringProperty(name, debugGetCreatorChain(10));
3654 }
3655
3656 // This is used to verify that Element objects move through life in an
3657 // orderly fashion.
3658 _ElementLifecycle _lifecycleState = _ElementLifecycle.initial;
3659
3660 /// Calls the argument for each child. Must be overridden by subclasses that
3661 /// support having children.
3662 ///
3663 /// There is no guaranteed order in which the children will be visited, though
3664 /// it should be consistent over time.
3665 ///
3666 /// Calling this during build is dangerous: the child list might still be
3667 /// being updated at that point, so the children might not be constructed yet,
3668 /// or might be old children that are going to be replaced. This method should
3669 /// only be called if it is provable that the children are available.
3670 void visitChildren(ElementVisitor visitor) { }
3671
3672 /// Calls the argument for each child considered onstage.
3673 ///
3674 /// Classes like [Offstage] and [Overlay] override this method to hide their
3675 /// children.
3676 ///
3677 /// Being onstage affects the element's discoverability during testing when
3678 /// you use Flutter's [Finder] objects. For example, when you instruct the
3679 /// test framework to tap on a widget, by default the finder will look for
3680 /// onstage elements and ignore the offstage ones.
3681 ///
3682 /// The default implementation defers to [visitChildren] and therefore treats
3683 /// the element as onstage.
3684 ///
3685 /// See also:
3686 ///
3687 /// * [Offstage] widget that hides its children.
3688 /// * [Finder] that skips offstage widgets by default.
3689 /// * [RenderObject.visitChildrenForSemantics], in contrast to this method,
3690 /// designed specifically for excluding parts of the UI from the semantics
3691 /// tree.
3692 void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
3693
3694 /// Wrapper around [visitChildren] for [BuildContext].
3695 @override
3696 void visitChildElements(ElementVisitor visitor) {
3697 assert(() {
3698 if (owner == null || !owner!._debugStateLocked) {
3699 return true;
3700 }
3701 throw FlutterError.fromParts(<DiagnosticsNode>[
3702 ErrorSummary('visitChildElements() called during build.'),
3703 ErrorDescription(
3704 "The BuildContext.visitChildElements() method can't be called during "
3705 'build because the child list is still being updated at that point, '
3706 'so the children might not be constructed yet, or might be old children '
3707 'that are going to be replaced.',
3708 ),
3709 ]);
3710 }());
3711 visitChildren(visitor);
3712 }
3713
3714 /// Update the given child with the given new configuration.
3715 ///
3716 /// This method is the core of the widgets system. It is called each time we
3717 /// are to add, update, or remove a child based on an updated configuration.
3718 ///
3719 /// The `newSlot` argument specifies the new value for this element's [slot].
3720 ///
3721 /// If the `child` is null, and the `newWidget` is not null, then we have a new
3722 /// child for which we need to create an [Element], configured with `newWidget`.
3723 ///
3724 /// If the `newWidget` is null, and the `child` is not null, then we need to
3725 /// remove it because it no longer has a configuration.
3726 ///
3727 /// If neither are null, then we need to update the `child`'s configuration to
3728 /// be the new configuration given by `newWidget`. If `newWidget` can be given
3729 /// to the existing child (as determined by [Widget.canUpdate]), then it is so
3730 /// given. Otherwise, the old child needs to be disposed and a new child
3731 /// created for the new configuration.
3732 ///
3733 /// If both are null, then we don't have a child and won't have a child, so we
3734 /// do nothing.
3735 ///
3736 /// The [updateChild] method returns the new child, if it had to create one,
3737 /// or the child that was passed in, if it just had to update the child, or
3738 /// null, if it removed the child and did not replace it.
3739 ///
3740 /// The following table summarizes the above:
3741 ///
3742 /// | | **newWidget == null** | **newWidget != null** |
3743 /// | :-----------------: | :--------------------- | :---------------------- |
3744 /// | **child == null** | Returns null. | Returns new [Element]. |
3745 /// | **child != null** | Old child is removed, returns null. | Old child updated if possible, returns child or new [Element]. |
3746 ///
3747 /// The `newSlot` argument is used only if `newWidget` is not null. If `child`
3748 /// is null (or if the old child cannot be updated), then the `newSlot` is
3749 /// given to the new [Element] that is created for the child, via
3750 /// [inflateWidget]. If `child` is not null (and the old child _can_ be
3751 /// updated), then the `newSlot` is given to [updateSlotForChild] to update
3752 /// its slot, in case it has moved around since it was last built.
3753 ///
3754 /// See the [RenderObjectElement] documentation for more information on slots.
3755 @protected
3756 @pragma('vm:prefer-inline')
3757 Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
3758 if (newWidget == null) {
3759 if (child != null) {
3760 deactivateChild(child);
3761 }
3762 return null;
3763 }
3764
3765 final Element newChild;
3766 if (child != null) {
3767 bool hasSameSuperclass = true;
3768 // When the type of a widget is changed between Stateful and Stateless via
3769 // hot reload, the element tree will end up in a partially invalid state.
3770 // That is, if the widget was a StatefulWidget and is now a StatelessWidget,
3771 // then the element tree currently contains a StatefulElement that is incorrectly
3772 // referencing a StatelessWidget (and likewise with StatelessElement).
3773 //
3774 // To avoid crashing due to type errors, we need to gently guide the invalid
3775 // element out of the tree. To do so, we ensure that the `hasSameSuperclass` condition
3776 // returns false which prevents us from trying to update the existing element
3777 // incorrectly.
3778 //
3779 // For the case where the widget becomes Stateful, we also need to avoid
3780 // accessing `StatelessElement.widget` as the cast on the getter will
3781 // cause a type error to be thrown. Here we avoid that by short-circuiting
3782 // the `Widget.canUpdate` check once `hasSameSuperclass` is false.
3783 assert(() {
3784 final int oldElementClass = Element._debugConcreteSubtype(child);
3785 final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
3786 hasSameSuperclass = oldElementClass == newWidgetClass;
3787 return true;
3788 }());
3789 if (hasSameSuperclass && child.widget == newWidget) {
3790 // We don't insert a timeline event here, because otherwise it's
3791 // confusing that widgets that "don't update" (because they didn't
3792 // change) get "charged" on the timeline.
3793 if (child.slot != newSlot) {
3794 updateSlotForChild(child, newSlot);
3795 }
3796 newChild = child;
3797 } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
3798 if (child.slot != newSlot) {
3799 updateSlotForChild(child, newSlot);
3800 }
3801 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
3802 if (isTimelineTracked) {
3803 Map<String, String>? debugTimelineArguments;
3804 assert(() {
3805 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
3806 debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
3807 }
3808 return true;
3809 }());
3810 FlutterTimeline.startSync(
3811 '${newWidget.runtimeType}',
3812 arguments: debugTimelineArguments,
3813 );
3814 }
3815 child.update(newWidget);
3816 if (isTimelineTracked) {
3817 FlutterTimeline.finishSync();
3818 }
3819 assert(child.widget == newWidget);
3820 assert(() {
3821 child.owner!._debugElementWasRebuilt(child);
3822 return true;
3823 }());
3824 newChild = child;
3825 } else {
3826 deactivateChild(child);
3827 assert(child._parent == null);
3828 // The [debugProfileBuildsEnabled] code for this branch is inside
3829 // [inflateWidget], since some [Element]s call [inflateWidget] directly
3830 // instead of going through [updateChild].
3831 newChild = inflateWidget(newWidget, newSlot);
3832 }
3833 } else {
3834 // The [debugProfileBuildsEnabled] code for this branch is inside
3835 // [inflateWidget], since some [Element]s call [inflateWidget] directly
3836 // instead of going through [updateChild].
3837 newChild = inflateWidget(newWidget, newSlot);
3838 }
3839
3840 assert(() {
3841 if (child != null) {
3842 _debugRemoveGlobalKeyReservation(child);
3843 }
3844 final Key? key = newWidget.key;
3845 if (key is GlobalKey) {
3846 assert(owner != null);
3847 owner!._debugReserveGlobalKeyFor(this, newChild, key);
3848 }
3849 return true;
3850 }());
3851
3852 return newChild;
3853 }
3854
3855 /// Updates the children of this element to use new widgets.
3856 ///
3857 /// Attempts to update the given old children list using the given new
3858 /// widgets, removing obsolete elements and introducing new ones as necessary,
3859 /// and then returns the new child list.
3860 ///
3861 /// During this function the `oldChildren` list must not be modified. If the
3862 /// caller wishes to remove elements from `oldChildren` reentrantly while
3863 /// this function is on the stack, the caller can supply a `forgottenChildren`
3864 /// argument, which can be modified while this function is on the stack.
3865 /// Whenever this function reads from `oldChildren`, this function first
3866 /// checks whether the child is in `forgottenChildren`. If it is, the function
3867 /// acts as if the child was not in `oldChildren`.
3868 ///
3869 /// This function is a convenience wrapper around [updateChild], which updates
3870 /// each individual child. If `slots` is non-null, the value for the `newSlot`
3871 /// argument of [updateChild] is retrieved from that list using the index that
3872 /// the currently processed `child` corresponds to in the `newWidgets` list
3873 /// (`newWidgets` and `slots` must have the same length). If `slots` is null,
3874 /// an [IndexedSlot<Element>] is used as the value for the `newSlot` argument.
3875 /// In that case, [IndexedSlot.index] is set to the index that the currently
3876 /// processed `child` corresponds to in the `newWidgets` list and
3877 /// [IndexedSlot.value] is set to the [Element] of the previous widget in that
3878 /// list (or null if it is the first child).
3879 ///
3880 /// When the [slot] value of an [Element] changes, its
3881 /// associated [renderObject] needs to move to a new position in the child
3882 /// list of its parents. If that [RenderObject] organizes its children in a
3883 /// linked list (as is done by the [ContainerRenderObjectMixin]) this can
3884 /// be implemented by re-inserting the child [RenderObject] into the
3885 /// list after the [RenderObject] associated with the [Element] provided as
3886 /// [IndexedSlot.value] in the [slot] object.
3887 ///
3888 /// Using the previous sibling as a [slot] is not enough, though, because
3889 /// child [RenderObject]s are only moved around when the [slot] of their
3890 /// associated [RenderObjectElement]s is updated. When the order of child
3891 /// [Element]s is changed, some elements in the list may move to a new index
3892 /// but still have the same previous sibling. For example, when
3893 /// `[e1, e2, e3, e4]` is changed to `[e1, e3, e4, e2]` the element e4
3894 /// continues to have e3 as a previous sibling even though its index in the list
3895 /// has changed and its [RenderObject] needs to move to come before e2's
3896 /// [RenderObject]. In order to trigger this move, a new [slot] value needs to
3897 /// be assigned to its [Element] whenever its index in its
3898 /// parent's child list changes. Using an [IndexedSlot<Element>] achieves
3899 /// exactly that and also ensures that the underlying parent [RenderObject]
3900 /// knows where a child needs to move to in a linked list by providing its new
3901 /// previous sibling.
3902 @protected
3903 List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element>? forgottenChildren, List<Object?>? slots }) {
3904 assert(slots == null || newWidgets.length == slots.length);
3905
3906 Element? replaceWithNullIfForgotten(Element child) {
3907 return forgottenChildren != null && forgottenChildren.contains(child) ? null : child;
3908 }
3909
3910 Object? slotFor(int newChildIndex, Element? previousChild) {
3911 return slots != null
3912 ? slots[newChildIndex]
3913 : IndexedSlot<Element?>(newChildIndex, previousChild);
3914 }
3915
3916 // This attempts to diff the new child list (newWidgets) with
3917 // the old child list (oldChildren), and produce a new list of elements to
3918 // be the new list of child elements of this element. The called of this
3919 // method is expected to update this render object accordingly.
3920
3921 // The cases it tries to optimize for are:
3922 // - the old list is empty
3923 // - the lists are identical
3924 // - there is an insertion or removal of one or more widgets in
3925 // only one place in the list
3926 // If a widget with a key is in both lists, it will be synced.
3927 // Widgets without keys might be synced but there is no guarantee.
3928
3929 // The general approach is to sync the entire new list backwards, as follows:
3930 // 1. Walk the lists from the top, syncing nodes, until you no longer have
3931 // matching nodes.
3932 // 2. Walk the lists from the bottom, without syncing nodes, until you no
3933 // longer have matching nodes. We'll sync these nodes at the end. We
3934 // don't sync them now because we want to sync all the nodes in order
3935 // from beginning to end.
3936 // At this point we narrowed the old and new lists to the point
3937 // where the nodes no longer match.
3938 // 3. Walk the narrowed part of the old list to get the list of
3939 // keys and sync null with non-keyed items.
3940 // 4. Walk the narrowed part of the new list forwards:
3941 // * Sync non-keyed items with null
3942 // * Sync keyed items with the source if it exists, else with null.
3943 // 5. Walk the bottom of the list again, syncing the nodes.
3944 // 6. Sync null with any items in the list of keys that are still
3945 // mounted.
3946
3947 int newChildrenTop = 0;
3948 int oldChildrenTop = 0;
3949 int newChildrenBottom = newWidgets.length - 1;
3950 int oldChildrenBottom = oldChildren.length - 1;
3951
3952 final List<Element> newChildren = List<Element>.filled(newWidgets.length, _NullElement.instance);
3953
3954 Element? previousChild;
3955
3956 // Update the top of the list.
3957 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
3958 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
3959 final Widget newWidget = newWidgets[newChildrenTop];
3960 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
3961 if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget)) {
3962 break;
3963 }
3964 final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
3965 assert(newChild._lifecycleState == _ElementLifecycle.active);
3966 newChildren[newChildrenTop] = newChild;
3967 previousChild = newChild;
3968 newChildrenTop += 1;
3969 oldChildrenTop += 1;
3970 }
3971
3972 // Scan the bottom of the list.
3973 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
3974 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);
3975 final Widget newWidget = newWidgets[newChildrenBottom];
3976 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
3977 if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget)) {
3978 break;
3979 }
3980 oldChildrenBottom -= 1;
3981 newChildrenBottom -= 1;
3982 }
3983
3984 // Scan the old children in the middle of the list.
3985 final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
3986 Map<Key, Element>? oldKeyedChildren;
3987 if (haveOldChildren) {
3988 oldKeyedChildren = <Key, Element>{};
3989 while (oldChildrenTop <= oldChildrenBottom) {
3990 final Element? oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
3991 assert(oldChild == null || oldChild._lifecycleState == _ElementLifecycle.active);
3992 if (oldChild != null) {
3993 if (oldChild.widget.key != null) {
3994 oldKeyedChildren[oldChild.widget.key!] = oldChild;
3995 } else {
3996 deactivateChild(oldChild);
3997 }
3998 }
3999 oldChildrenTop += 1;
4000 }
4001 }
4002
4003 // Update the middle of the list.
4004 while (newChildrenTop <= newChildrenBottom) {
4005 Element? oldChild;
4006 final Widget newWidget = newWidgets[newChildrenTop];
4007 if (haveOldChildren) {
4008 final Key? key = newWidget.key;
4009 if (key != null) {
4010 oldChild = oldKeyedChildren![key];
4011 if (oldChild != null) {
4012 if (Widget.canUpdate(oldChild.widget, newWidget)) {
4013 // we found a match!
4014 // remove it from oldKeyedChildren so we don't unsync it later
4015 oldKeyedChildren.remove(key);
4016 } else {
4017 // Not a match, let's pretend we didn't see it for now.
4018 oldChild = null;
4019 }
4020 }
4021 }
4022 }
4023 assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));
4024 final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
4025 assert(newChild._lifecycleState == _ElementLifecycle.active);
4026 assert(oldChild == newChild || oldChild == null || oldChild._lifecycleState != _ElementLifecycle.active);
4027 newChildren[newChildrenTop] = newChild;
4028 previousChild = newChild;
4029 newChildrenTop += 1;
4030 }
4031
4032 // We've scanned the whole list.
4033 assert(oldChildrenTop == oldChildrenBottom + 1);
4034 assert(newChildrenTop == newChildrenBottom + 1);
4035 assert(newWidgets.length - newChildrenTop == oldChildren.length - oldChildrenTop);
4036 newChildrenBottom = newWidgets.length - 1;
4037 oldChildrenBottom = oldChildren.length - 1;
4038
4039 // Update the bottom of the list.
4040 while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4041 final Element oldChild = oldChildren[oldChildrenTop];
4042 assert(replaceWithNullIfForgotten(oldChild) != null);
4043 assert(oldChild._lifecycleState == _ElementLifecycle.active);
4044 final Widget newWidget = newWidgets[newChildrenTop];
4045 assert(Widget.canUpdate(oldChild.widget, newWidget));
4046 final Element newChild = updateChild(oldChild, newWidget, slotFor(newChildrenTop, previousChild))!;
4047 assert(newChild._lifecycleState == _ElementLifecycle.active);
4048 assert(oldChild == newChild || oldChild._lifecycleState != _ElementLifecycle.active);
4049 newChildren[newChildrenTop] = newChild;
4050 previousChild = newChild;
4051 newChildrenTop += 1;
4052 oldChildrenTop += 1;
4053 }
4054
4055 // Clean up any of the remaining middle nodes from the old list.
4056 if (haveOldChildren && oldKeyedChildren!.isNotEmpty) {
4057 for (final Element oldChild in oldKeyedChildren.values) {
4058 if (forgottenChildren == null || !forgottenChildren.contains(oldChild)) {
4059 deactivateChild(oldChild);
4060 }
4061 }
4062 }
4063 assert(newChildren.every((Element element) => element is! _NullElement));
4064 return newChildren;
4065 }
4066
4067 /// Add this element to the tree in the given slot of the given parent.
4068 ///
4069 /// The framework calls this function when a newly created element is added to
4070 /// the tree for the first time. Use this method to initialize state that
4071 /// depends on having a parent. State that is independent of the parent can
4072 /// more easily be initialized in the constructor.
4073 ///
4074 /// This method transitions the element from the "initial" lifecycle state to
4075 /// the "active" lifecycle state.
4076 ///
4077 /// Subclasses that override this method are likely to want to also override
4078 /// [update], [visitChildren], [RenderObjectElement.insertRenderObjectChild],
4079 /// [RenderObjectElement.moveRenderObjectChild], and
4080 /// [RenderObjectElement.removeRenderObjectChild].
4081 ///
4082 /// Implementations of this method should start with a call to the inherited
4083 /// method, as in `super.mount(parent, newSlot)`.
4084 @mustCallSuper
4085 void mount(Element? parent, Object? newSlot) {
4086 assert(_lifecycleState == _ElementLifecycle.initial);
4087 assert(_parent == null);
4088 assert(parent == null || parent._lifecycleState == _ElementLifecycle.active);
4089 assert(slot == null);
4090 _parent = parent;
4091 _slot = newSlot;
4092 _lifecycleState = _ElementLifecycle.active;
4093 _depth = _parent != null ? _parent!.depth + 1 : 1;
4094 if (parent != null) {
4095 // Only assign ownership if the parent is non-null. If parent is null
4096 // (the root node), the owner should have already been assigned.
4097 // See RootRenderObjectElement.assignOwner().
4098 _owner = parent.owner;
4099 }
4100 assert(owner != null);
4101 final Key? key = widget.key;
4102 if (key is GlobalKey) {
4103 owner!._registerGlobalKey(key, this);
4104 }
4105 _updateInheritance();
4106 attachNotificationTree();
4107 }
4108
4109 void _debugRemoveGlobalKeyReservation(Element child) {
4110 assert(owner != null);
4111 owner!._debugRemoveGlobalKeyReservationFor(this, child);
4112 }
4113
4114 /// Change the widget used to configure this element.
4115 ///
4116 /// The framework calls this function when the parent wishes to use a
4117 /// different widget to configure this element. The new widget is guaranteed
4118 /// to have the same [runtimeType] as the old widget.
4119 ///
4120 /// This function is called only during the "active" lifecycle state.
4121 @mustCallSuper
4122 void update(covariant Widget newWidget) {
4123 // This code is hot when hot reloading, so we try to
4124 // only call _AssertionError._evaluateAssertion once.
4125 assert(
4126 _lifecycleState == _ElementLifecycle.active
4127 && newWidget != widget
4128 && Widget.canUpdate(widget, newWidget),
4129 );
4130 // This Element was told to update and we can now release all the global key
4131 // reservations of forgotten children. We cannot do this earlier because the
4132 // forgotten children still represent global key duplications if the element
4133 // never updates (the forgotten children are not removed from the tree
4134 // until the call to update happens)
4135 assert(() {
4136 _debugForgottenChildrenWithGlobalKey?.forEach(_debugRemoveGlobalKeyReservation);
4137 _debugForgottenChildrenWithGlobalKey?.clear();
4138 return true;
4139 }());
4140 _widget = newWidget;
4141 }
4142
4143 /// Change the slot that the given child occupies in its parent.
4144 ///
4145 /// Called by [MultiChildRenderObjectElement], and other [RenderObjectElement]
4146 /// subclasses that have multiple children, when child moves from one position
4147 /// to another in this element's child list.
4148 @protected
4149 void updateSlotForChild(Element child, Object? newSlot) {
4150 assert(_lifecycleState == _ElementLifecycle.active);
4151 assert(child._parent == this);
4152 void visit(Element element) {
4153 element.updateSlot(newSlot);
4154 final Element? descendant = element.renderObjectAttachingChild;
4155 if (descendant != null) {
4156 visit(descendant);
4157 }
4158 }
4159 visit(child);
4160 }
4161
4162 /// Called by [updateSlotForChild] when the framework needs to change the slot
4163 /// that this [Element] occupies in its ancestor.
4164 @protected
4165 @mustCallSuper
4166 void updateSlot(Object? newSlot) {
4167 assert(_lifecycleState == _ElementLifecycle.active);
4168 assert(_parent != null);
4169 assert(_parent!._lifecycleState == _ElementLifecycle.active);
4170 _slot = newSlot;
4171 }
4172
4173 void _updateDepth(int parentDepth) {
4174 final int expectedDepth = parentDepth + 1;
4175 if (_depth < expectedDepth) {
4176 _depth = expectedDepth;
4177 visitChildren((Element child) {
4178 child._updateDepth(expectedDepth);
4179 });
4180 }
4181 }
4182
4183 /// Remove [renderObject] from the render tree.
4184 ///
4185 /// The default implementation of this function calls
4186 /// [detachRenderObject] recursively on each child. The
4187 /// [RenderObjectElement.detachRenderObject] override does the actual work of
4188 /// removing [renderObject] from the render tree.
4189 ///
4190 /// This is called by [deactivateChild].
4191 void detachRenderObject() {
4192 visitChildren((Element child) {
4193 child.detachRenderObject();
4194 });
4195 _slot = null;
4196 }
4197
4198 /// Add [renderObject] to the render tree at the location specified by `newSlot`.
4199 ///
4200 /// The default implementation of this function calls
4201 /// [attachRenderObject] recursively on each child. The
4202 /// [RenderObjectElement.attachRenderObject] override does the actual work of
4203 /// adding [renderObject] to the render tree.
4204 ///
4205 /// The `newSlot` argument specifies the new value for this element's [slot].
4206 void attachRenderObject(Object? newSlot) {
4207 assert(slot == null);
4208 visitChildren((Element child) {
4209 child.attachRenderObject(newSlot);
4210 });
4211 _slot = newSlot;
4212 }
4213
4214 Element? _retakeInactiveElement(GlobalKey key, Widget newWidget) {
4215 // The "inactivity" of the element being retaken here may be forward-looking: if
4216 // we are taking an element with a GlobalKey from an element that currently has
4217 // it as a child, then we know that element will soon no longer have that
4218 // element as a child. The only way that assumption could be false is if the
4219 // global key is being duplicated, and we'll try to track that using the
4220 // _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans call below.
4221 final Element? element = key._currentElement;
4222 if (element == null) {
4223 return null;
4224 }
4225 if (!Widget.canUpdate(element.widget, newWidget)) {
4226 return null;
4227 }
4228 assert(() {
4229 if (debugPrintGlobalKeyedWidgetLifecycle) {
4230 debugPrint('Attempting to take $element from ${element._parent ?? "inactive elements list"} to put in $this.');
4231 }
4232 return true;
4233 }());
4234 final Element? parent = element._parent;
4235 if (parent != null) {
4236 assert(() {
4237 if (parent == this) {
4238 throw FlutterError.fromParts(<DiagnosticsNode>[
4239 ErrorSummary("A GlobalKey was used multiple times inside one widget's child list."),
4240 DiagnosticsProperty<GlobalKey>('The offending GlobalKey was', key),
4241 parent.describeElement('The parent of the widgets with that key was'),
4242 element.describeElement('The first child to get instantiated with that key became'),
4243 DiagnosticsProperty<Widget>('The second child that was to be instantiated with that key was', widget, style: DiagnosticsTreeStyle.errorProperty),
4244 ErrorDescription('A GlobalKey can only be specified on one widget at a time in the widget tree.'),
4245 ]);
4246 }
4247 parent.owner!._debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(
4248 parent,
4249 key,
4250 );
4251 return true;
4252 }());
4253 parent.forgetChild(element);
4254 parent.deactivateChild(element);
4255 }
4256 assert(element._parent == null);
4257 owner!._inactiveElements.remove(element);
4258 return element;
4259 }
4260
4261 /// Create an element for the given widget and add it as a child of this
4262 /// element in the given slot.
4263 ///
4264 /// This method is typically called by [updateChild] but can be called
4265 /// directly by subclasses that need finer-grained control over creating
4266 /// elements.
4267 ///
4268 /// If the given widget has a global key and an element already exists that
4269 /// has a widget with that global key, this function will reuse that element
4270 /// (potentially grafting it from another location in the tree or reactivating
4271 /// it from the list of inactive elements) rather than creating a new element.
4272 ///
4273 /// The `newSlot` argument specifies the new value for this element's [slot].
4274 ///
4275 /// The element returned by this function will already have been mounted and
4276 /// will be in the "active" lifecycle state.
4277 @protected
4278 @pragma('vm:prefer-inline')
4279 Element inflateWidget(Widget newWidget, Object? newSlot) {
4280 final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
4281 if (isTimelineTracked) {
4282 Map<String, String>? debugTimelineArguments;
4283 assert(() {
4284 if (kDebugMode && debugEnhanceBuildTimelineArguments) {
4285 debugTimelineArguments = newWidget.toDiagnosticsNode().toTimelineArguments();
4286 }
4287 return true;
4288 }());
4289 FlutterTimeline.startSync(
4290 '${newWidget.runtimeType}',
4291 arguments: debugTimelineArguments,
4292 );
4293 }
4294
4295 try {
4296 final Key? key = newWidget.key;
4297 if (key is GlobalKey) {
4298 final Element? newChild = _retakeInactiveElement(key, newWidget);
4299 if (newChild != null) {
4300 assert(newChild._parent == null);
4301 assert(() {
4302 _debugCheckForCycles(newChild);
4303 return true;
4304 }());
4305 try {
4306 newChild._activateWithParent(this, newSlot);
4307 } catch (_) {
4308 // Attempt to do some clean-up if activation fails to leave tree in a reasonable state.
4309 try {
4310 deactivateChild(newChild);
4311 } catch (_) {
4312 // Clean-up failed. Only surface original exception.
4313 }
4314 rethrow;
4315 }
4316 final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
4317 assert(newChild == updatedChild);
4318 return updatedChild!;
4319 }
4320 }
4321 final Element newChild = newWidget.createElement();
4322 assert(() {
4323 _debugCheckForCycles(newChild);
4324 return true;
4325 }());
4326 newChild.mount(this, newSlot);
4327 assert(newChild._lifecycleState == _ElementLifecycle.active);
4328
4329 return newChild;
4330 } finally {
4331 if (isTimelineTracked) {
4332 FlutterTimeline.finishSync();
4333 }
4334 }
4335 }
4336
4337 void _debugCheckForCycles(Element newChild) {
4338 assert(newChild._parent == null);
4339 assert(() {
4340 Element node = this;
4341 while (node._parent != null) {
4342 node = node._parent!;
4343 }
4344 assert(node != newChild); // indicates we are about to create a cycle
4345 return true;
4346 }());
4347 }
4348
4349 /// Move the given element to the list of inactive elements and detach its
4350 /// render object from the render tree.
4351 ///
4352 /// This method stops the given element from being a child of this element by
4353 /// detaching its render object from the render tree and moving the element to
4354 /// the list of inactive elements.
4355 ///
4356 /// This method (indirectly) calls [deactivate] on the child.
4357 ///
4358 /// The caller is responsible for removing the child from its child model.
4359 /// Typically [deactivateChild] is called by the element itself while it is
4360 /// updating its child model; however, during [GlobalKey] reparenting, the new
4361 /// parent proactively calls the old parent's [deactivateChild], first using
4362 /// [forgetChild] to cause the old parent to update its child model.
4363 @protected
4364 void deactivateChild(Element child) {
4365 assert(child._parent == this);
4366 child._parent = null;
4367 child.detachRenderObject();
4368 owner!._inactiveElements.add(child); // this eventually calls child.deactivate()
4369 assert(() {
4370 if (debugPrintGlobalKeyedWidgetLifecycle) {
4371 if (child.widget.key is GlobalKey) {
4372 debugPrint('Deactivated $child (keyed child of $this)');
4373 }
4374 }
4375 return true;
4376 }());
4377 }
4378
4379 // The children that have been forgotten by forgetChild. This will be used in
4380 // [update] to remove the global key reservations of forgotten children.
4381 //
4382 // In Profile/Release mode this field is initialized to `null`. The Dart compiler can
4383 // eliminate unused fields, but not their initializers.
4384 @_debugOnly
4385 final Set<Element>? _debugForgottenChildrenWithGlobalKey = kDebugMode ? HashSet<Element>() : null;
4386
4387 /// Remove the given child from the element's child list, in preparation for
4388 /// the child being reused elsewhere in the element tree.
4389 ///
4390 /// This updates the child model such that, e.g., [visitChildren] does not
4391 /// walk that child anymore.
4392 ///
4393 /// The element will still have a valid parent when this is called, and the
4394 /// child's [Element.slot] value will be valid in the context of that parent.
4395 /// After this is called, [deactivateChild] is called to sever the link to
4396 /// this object.
4397 ///
4398 /// The [update] is responsible for updating or creating the new child that
4399 /// will replace this [child].
4400 @protected
4401 @mustCallSuper
4402 void forgetChild(Element child) {
4403 // This method is called on the old parent when the given child (with a
4404 // global key) is given a new parent. We cannot remove the global key
4405 // reservation directly in this method because the forgotten child is not
4406 // removed from the tree until this Element is updated in [update]. If
4407 // [update] is never called, the forgotten child still represents a global
4408 // key duplication that we need to catch.
4409 assert(() {
4410 if (child.widget.key is GlobalKey) {
4411 _debugForgottenChildrenWithGlobalKey?.add(child);
4412 }
4413 return true;
4414 }());
4415 }
4416
4417 void _activateWithParent(Element parent, Object? newSlot) {
4418 assert(_lifecycleState == _ElementLifecycle.inactive);
4419 _parent = parent;
4420 assert(() {
4421 if (debugPrintGlobalKeyedWidgetLifecycle) {
4422 debugPrint('Reactivating $this (now child of $_parent).');
4423 }
4424 return true;
4425 }());
4426 _updateDepth(_parent!.depth);
4427 _activateRecursively(this);
4428 attachRenderObject(newSlot);
4429 assert(_lifecycleState == _ElementLifecycle.active);
4430 }
4431
4432 static void _activateRecursively(Element element) {
4433 assert(element._lifecycleState == _ElementLifecycle.inactive);
4434 element.activate();
4435 assert(element._lifecycleState == _ElementLifecycle.active);
4436 element.visitChildren(_activateRecursively);
4437 }
4438
4439 /// Transition from the "inactive" to the "active" lifecycle state.
4440 ///
4441 /// The framework calls this method when a previously deactivated element has
4442 /// been reincorporated into the tree. The framework does not call this method
4443 /// the first time an element becomes active (i.e., from the "initial"
4444 /// lifecycle state). Instead, the framework calls [mount] in that situation.
4445 ///
4446 /// See the lifecycle documentation for [Element] for additional information.
4447 ///
4448 /// Implementations of this method should start with a call to the inherited
4449 /// method, as in `super.activate()`.
4450 @mustCallSuper
4451 void activate() {
4452 assert(_lifecycleState == _ElementLifecycle.inactive);
4453 assert(owner != null);
4454 final bool hadDependencies = (_dependencies != null && _dependencies!.isNotEmpty) || _hadUnsatisfiedDependencies;
4455 _lifecycleState = _ElementLifecycle.active;
4456 // We unregistered our dependencies in deactivate, but never cleared the list.
4457 // Since we're going to be reused, let's clear our list now.
4458 _dependencies?.clear();
4459 _hadUnsatisfiedDependencies = false;
4460 _updateInheritance();
4461 attachNotificationTree();
4462 if (_dirty) {
4463 owner!.scheduleBuildFor(this);
4464 }
4465 if (hadDependencies) {
4466 didChangeDependencies();
4467 }
4468 }
4469
4470 /// Transition from the "active" to the "inactive" lifecycle state.
4471 ///
4472 /// The framework calls this method when a previously active element is moved
4473 /// to the list of inactive elements. While in the inactive state, the element
4474 /// will not appear on screen. The element can remain in the inactive state
4475 /// only until the end of the current animation frame. At the end of the
4476 /// animation frame, if the element has not be reactivated, the framework will
4477 /// unmount the element.
4478 ///
4479 /// This is (indirectly) called by [deactivateChild].
4480 ///
4481 /// See the lifecycle documentation for [Element] for additional information.
4482 ///
4483 /// Implementations of this method should end with a call to the inherited
4484 /// method, as in `super.deactivate()`.
4485 @mustCallSuper
4486 void deactivate() {
4487 assert(_lifecycleState == _ElementLifecycle.active);
4488 assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
4489 if (_dependencies != null && _dependencies!.isNotEmpty) {
4490 for (final InheritedElement dependency in _dependencies!) {
4491 dependency._dependents.remove(this);
4492 }
4493 // For expediency, we don't actually clear the list here, even though it's
4494 // no longer representative of what we are registered with. If we never
4495 // get re-used, it doesn't matter. If we do, then we'll clear the list in
4496 // activate(). The benefit of this is that it allows Element's activate()
4497 // implementation to decide whether to rebuild based on whether we had
4498 // dependencies here.
4499 }
4500 _inheritedElements = null;
4501 _lifecycleState = _ElementLifecycle.inactive;
4502 }
4503
4504 /// Called, in debug mode, after children have been deactivated (see [deactivate]).
4505 ///
4506 /// This method is not called in release builds.
4507 @mustCallSuper
4508 void debugDeactivated() {
4509 assert(_lifecycleState == _ElementLifecycle.inactive);
4510 }
4511
4512 /// Transition from the "inactive" to the "defunct" lifecycle state.
4513 ///
4514 /// Called when the framework determines that an inactive element will never
4515 /// be reactivated. At the end of each animation frame, the framework calls
4516 /// [unmount] on any remaining inactive elements, preventing inactive elements
4517 /// from remaining inactive for longer than a single animation frame.
4518 ///
4519 /// After this function is called, the element will not be incorporated into
4520 /// the tree again.
4521 ///
4522 /// Any resources this element holds should be released at this point. For
4523 /// example, [RenderObjectElement.unmount] calls [RenderObject.dispose] and
4524 /// nulls out its reference to the render object.
4525 ///
4526 /// See the lifecycle documentation for [Element] for additional information.
4527 ///
4528 /// Implementations of this method should end with a call to the inherited
4529 /// method, as in `super.unmount()`.
4530 @mustCallSuper
4531 void unmount() {
4532 assert(_lifecycleState == _ElementLifecycle.inactive);
4533 assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
4534 assert(owner != null);
4535 if (kFlutterMemoryAllocationsEnabled) {
4536 MemoryAllocations.instance.dispatchObjectDisposed(object: this);
4537 }
4538 // Use the private property to avoid a CastError during hot reload.
4539 final Key? key = _widget?.key;
4540 if (key is GlobalKey) {
4541 owner!._unregisterGlobalKey(key, this);
4542 }
4543 // Release resources to reduce the severity of memory leaks caused by
4544 // defunct, but accidentally retained Elements.
4545 _widget = null;
4546 _dependencies = null;
4547 _lifecycleState = _ElementLifecycle.defunct;
4548 }
4549
4550 /// Whether the child in the provided `slot` (or one of its descendants) must
4551 /// insert a [RenderObject] into its ancestor [RenderObjectElement] by calling
4552 /// [RenderObjectElement.insertRenderObjectChild] on it.
4553 ///
4554 /// This method is used to define non-rendering zones in the element tree (see
4555 /// [WidgetsBinding] for an explanation of rendering and non-rendering zones):
4556 ///
4557 /// Most branches of the [Element] tree are expected to eventually insert a
4558 /// [RenderObject] into their [RenderObjectElement] ancestor to construct the
4559 /// render tree. However, there is a notable exception: an [Element] may
4560 /// expect that the occupant of a certain child slot creates a new independent
4561 /// render tree and therefore is not allowed to insert a render object into
4562 /// the existing render tree. Those elements must return false from this
4563 /// method for the slot in question to signal to the child in that slot that
4564 /// it must not call [RenderObjectElement.insertRenderObjectChild] on its
4565 /// ancestor.
4566 ///
4567 /// As an example, the element backing the [ViewAnchor] returns false from
4568 /// this method for the [ViewAnchor.view] slot to enforce that it is occupied
4569 /// by e.g. a [View] widget, which will ultimately bootstrap a separate
4570 /// render tree for that view. Another example is the [ViewCollection] widget,
4571 /// which returns false for all its slots for the same reason.
4572 ///
4573 /// Overriding this method is not common, as elements behaving in the way
4574 /// described above are rare.
4575 bool debugExpectsRenderObjectForSlot(Object? slot) => true;
4576
4577 @override
4578 RenderObject? findRenderObject() {
4579 assert(() {
4580 if (_lifecycleState != _ElementLifecycle.active) {
4581 throw FlutterError.fromParts(<DiagnosticsNode>[
4582 ErrorSummary('Cannot get renderObject of inactive element.'),
4583 ErrorDescription(
4584 'In order for an element to have a valid renderObject, it must be '
4585 'active, which means it is part of the tree.\n'
4586 'Instead, this element is in the $_lifecycleState state.\n'
4587 'If you called this method from a State object, consider guarding '
4588 'it with State.mounted.',
4589 ),
4590 describeElement('The findRenderObject() method was called for the following element'),
4591 ]);
4592 }
4593 return true;
4594 }());
4595 return renderObject;
4596 }
4597
4598 @override
4599 Size? get size {
4600 assert(() {
4601 if (_lifecycleState != _ElementLifecycle.active) {
4602 // TODO(jacobr): is this a good separation into contract and violation?
4603 // I have added a line of white space.
4604 throw FlutterError.fromParts(<DiagnosticsNode>[
4605 ErrorSummary('Cannot get size of inactive element.'),
4606 ErrorDescription(
4607 'In order for an element to have a valid size, the element must be '
4608 'active, which means it is part of the tree.\n'
4609 'Instead, this element is in the $_lifecycleState state.',
4610 ),
4611 describeElement('The size getter was called for the following element'),
4612 ]);
4613 }
4614 if (owner!._debugBuilding) {
4615 throw FlutterError.fromParts(<DiagnosticsNode>[
4616 ErrorSummary('Cannot get size during build.'),
4617 ErrorDescription(
4618 'The size of this render object has not yet been determined because '
4619 'the framework is still in the process of building widgets, which '
4620 'means the render tree for this frame has not yet been determined. '
4621 'The size getter should only be called from paint callbacks or '
4622 'interaction event handlers (e.g. gesture callbacks).',
4623 ),
4624 ErrorSpacer(),
4625 ErrorHint(
4626 'If you need some sizing information during build to decide which '
4627 'widgets to build, consider using a LayoutBuilder widget, which can '
4628 'tell you the layout constraints at a given location in the tree. See '
4629 '<https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html> '
4630 'for more details.',
4631 ),
4632 ErrorSpacer(),
4633 describeElement('The size getter was called for the following element'),
4634 ]);
4635 }
4636 return true;
4637 }());
4638 final RenderObject? renderObject = findRenderObject();
4639 assert(() {
4640 if (renderObject == null) {
4641 throw FlutterError.fromParts(<DiagnosticsNode>[
4642 ErrorSummary('Cannot get size without a render object.'),
4643 ErrorHint(
4644 'In order for an element to have a valid size, the element must have '
4645 'an associated render object. This element does not have an associated '
4646 'render object, which typically means that the size getter was called '
4647 'too early in the pipeline (e.g., during the build phase) before the '
4648 'framework has created the render tree.',
4649 ),
4650 describeElement('The size getter was called for the following element'),
4651 ]);
4652 }
4653 if (renderObject is RenderSliver) {
4654 throw FlutterError.fromParts(<DiagnosticsNode>[
4655 ErrorSummary('Cannot get size from a RenderSliver.'),
4656 ErrorHint(
4657 'The render object associated with this element is a '
4658 '${renderObject.runtimeType}, which is a subtype of RenderSliver. '
4659 'Slivers do not have a size per se. They have a more elaborate '
4660 'geometry description, which can be accessed by calling '
4661 'findRenderObject and then using the "geometry" getter on the '
4662 'resulting object.',
4663 ),
4664 describeElement('The size getter was called for the following element'),
4665 renderObject.describeForError('The associated render sliver was'),
4666 ]);
4667 }
4668 if (renderObject is! RenderBox) {
4669 throw FlutterError.fromParts(<DiagnosticsNode>[
4670 ErrorSummary('Cannot get size from a render object that is not a RenderBox.'),
4671 ErrorHint(
4672 'Instead of being a subtype of RenderBox, the render object associated '
4673 'with this element is a ${renderObject.runtimeType}. If this type of '
4674 'render object does have a size, consider calling findRenderObject '
4675 'and extracting its size manually.',
4676 ),
4677 describeElement('The size getter was called for the following element'),
4678 renderObject.describeForError('The associated render object was'),
4679 ]);
4680 }
4681 final RenderBox box = renderObject;
4682 if (!box.hasSize) {
4683 throw FlutterError.fromParts(<DiagnosticsNode>[
4684 ErrorSummary('Cannot get size from a render object that has not been through layout.'),
4685 ErrorHint(
4686 'The size of this render object has not yet been determined because '
4687 'this render object has not yet been through layout, which typically '
4688 'means that the size getter was called too early in the pipeline '
4689 '(e.g., during the build phase) before the framework has determined '
4690 'the size and position of the render objects during layout.',
4691 ),
4692 describeElement('The size getter was called for the following element'),
4693 box.describeForError('The render object from which the size was to be obtained was'),
4694 ]);
4695 }
4696 if (box.debugNeedsLayout) {
4697 throw FlutterError.fromParts(<DiagnosticsNode>[
4698 ErrorSummary('Cannot get size from a render object that has been marked dirty for layout.'),
4699 ErrorHint(
4700 'The size of this render object is ambiguous because this render object has '
4701 'been modified since it was last laid out, which typically means that the size '
4702 'getter was called too early in the pipeline (e.g., during the build phase) '
4703 'before the framework has determined the size and position of the render '
4704 'objects during layout.',
4705 ),
4706 describeElement('The size getter was called for the following element'),
4707 box.describeForError('The render object from which the size was to be obtained was'),
4708 ErrorHint(
4709 'Consider using debugPrintMarkNeedsLayoutStacks to determine why the render '
4710 'object in question is dirty, if you did not expect this.',
4711 ),
4712 ]);
4713 }
4714 return true;
4715 }());
4716 if (renderObject is RenderBox) {
4717 return renderObject.size;
4718 }
4719 return null;
4720 }
4721
4722 PersistentHashMap<Type, InheritedElement>? _inheritedElements;
4723 Set<InheritedElement>? _dependencies;
4724 bool _hadUnsatisfiedDependencies = false;
4725
4726 bool _debugCheckStateIsActiveForAncestorLookup() {
4727 assert(() {
4728 if (_lifecycleState != _ElementLifecycle.active) {
4729 throw FlutterError.fromParts(<DiagnosticsNode>[
4730 ErrorSummary("Looking up a deactivated widget's ancestor is unsafe."),
4731 ErrorDescription(
4732 "At this point the state of the widget's element tree is no longer "
4733 'stable.',
4734 ),
4735 ErrorHint(
4736 "To safely refer to a widget's ancestor in its dispose() method, "
4737 'save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() '
4738 "in the widget's didChangeDependencies() method.",
4739 ),
4740 ]);
4741 }
4742 return true;
4743 }());
4744 return true;
4745 }
4746
4747 /// Returns `true` if [dependOnInheritedElement] was previously called with [ancestor].
4748 @protected
4749 bool doesDependOnInheritedElement(InheritedElement ancestor) =>
4750 _dependencies != null && _dependencies!.contains(ancestor);
4751
4752 @override
4753 InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) {
4754 _dependencies ??= HashSet<InheritedElement>();
4755 _dependencies!.add(ancestor);
4756 ancestor.updateDependencies(this, aspect);
4757 return ancestor.widget as InheritedWidget;
4758 }
4759
4760 @override
4761 T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
4762 assert(_debugCheckStateIsActiveForAncestorLookup());
4763 final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T];
4764 if (ancestor != null) {
4765 return dependOnInheritedElement(ancestor, aspect: aspect) as T;
4766 }
4767 _hadUnsatisfiedDependencies = true;
4768 return null;
4769 }
4770
4771 @override
4772 T? getInheritedWidgetOfExactType<T extends InheritedWidget>() {
4773 return getElementForInheritedWidgetOfExactType<T>()?.widget as T?;
4774 }
4775
4776 @override
4777 InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
4778 assert(_debugCheckStateIsActiveForAncestorLookup());
4779 final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T];
4780 return ancestor;
4781 }
4782
4783 /// Called in [Element.mount] and [Element.activate] to register this element in
4784 /// the notification tree.
4785 ///
4786 /// This method is only exposed so that [NotifiableElementMixin] can be implemented.
4787 /// Subclasses of [Element] that wish to respond to notifications should mix that
4788 /// in instead.
4789 ///
4790 /// See also:
4791 /// * [NotificationListener], a widget that allows listening to notifications.
4792 @protected
4793 void attachNotificationTree() {
4794 _notificationTree = _parent?._notificationTree;
4795 }
4796
4797 void _updateInheritance() {
4798 assert(_lifecycleState == _ElementLifecycle.active);
4799 _inheritedElements = _parent?._inheritedElements;
4800 }
4801
4802 @override
4803 T? findAncestorWidgetOfExactType<T extends Widget>() {
4804 assert(_debugCheckStateIsActiveForAncestorLookup());
4805 Element? ancestor = _parent;
4806 while (ancestor != null && ancestor.widget.runtimeType != T) {
4807 ancestor = ancestor._parent;
4808 }
4809 return ancestor?.widget as T?;
4810 }
4811
4812 @override
4813 T? findAncestorStateOfType<T extends State<StatefulWidget>>() {
4814 assert(_debugCheckStateIsActiveForAncestorLookup());
4815 Element? ancestor = _parent;
4816 while (ancestor != null) {
4817 if (ancestor is StatefulElement && ancestor.state is T) {
4818 break;
4819 }
4820 ancestor = ancestor._parent;
4821 }
4822 final StatefulElement? statefulAncestor = ancestor as StatefulElement?;
4823 return statefulAncestor?.state as T?;
4824 }
4825
4826 @override
4827 T? findRootAncestorStateOfType<T extends State<StatefulWidget>>() {
4828 assert(_debugCheckStateIsActiveForAncestorLookup());
4829 Element? ancestor = _parent;
4830 StatefulElement? statefulAncestor;
4831 while (ancestor != null) {
4832 if (ancestor is StatefulElement && ancestor.state is T) {
4833 statefulAncestor = ancestor;
4834 }
4835 ancestor = ancestor._parent;
4836 }
4837 return statefulAncestor?.state as T?;
4838 }
4839
4840 @override
4841 T? findAncestorRenderObjectOfType<T extends RenderObject>() {
4842 assert(_debugCheckStateIsActiveForAncestorLookup());
4843 Element? ancestor = _parent;
4844 while (ancestor != null) {
4845 if (ancestor is RenderObjectElement && ancestor.renderObject is T) {
4846 return ancestor.renderObject as T;
4847 }
4848 ancestor = ancestor._parent;
4849 }
4850 return null;
4851 }
4852
4853 @override
4854 void visitAncestorElements(ConditionalElementVisitor visitor) {
4855 assert(_debugCheckStateIsActiveForAncestorLookup());
4856 Element? ancestor = _parent;
4857 while (ancestor != null && visitor(ancestor)) {
4858 ancestor = ancestor._parent;
4859 }
4860 }
4861
4862 /// Called when a dependency of this element changes.
4863 ///
4864 /// The [dependOnInheritedWidgetOfExactType] registers this element as depending on
4865 /// inherited information of the given type. When the information of that type
4866 /// changes at this location in the tree (e.g., because the [InheritedElement]
4867 /// updated to a new [InheritedWidget] and
4868 /// [InheritedWidget.updateShouldNotify] returned true), the framework calls
4869 /// this function to notify this element of the change.
4870 @mustCallSuper
4871 void didChangeDependencies() {
4872 assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
4873 assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
4874 markNeedsBuild();
4875 }
4876
4877 bool _debugCheckOwnerBuildTargetExists(String methodName) {
4878 assert(() {
4879 if (owner!._debugCurrentBuildTarget == null) {
4880 throw FlutterError.fromParts(<DiagnosticsNode>[
4881 ErrorSummary(
4882 '$methodName for ${widget.runtimeType} was called at an '
4883 'inappropriate time.',
4884 ),
4885 ErrorDescription('It may only be called while the widgets are being built.'),
4886 ErrorHint(
4887 'A possible cause of this error is when $methodName is called during '
4888 'one of:\n'
4889 ' * network I/O event\n'
4890 ' * file I/O event\n'
4891 ' * timer\n'
4892 ' * microtask (caused by Future.then, async/await, scheduleMicrotask)',
4893 ),
4894 ]);
4895 }
4896 return true;
4897 }());
4898 return true;
4899 }
4900
4901 /// Returns a description of what caused this element to be created.
4902 ///
4903 /// Useful for debugging the source of an element.
4904 String debugGetCreatorChain(int limit) {
4905 final List<String> chain = <String>[];
4906 Element? node = this;
4907 while (chain.length < limit && node != null) {
4908 chain.add(node.toStringShort());
4909 node = node._parent;
4910 }
4911 if (node != null) {
4912 chain.add('\u22EF');
4913 }
4914 return chain.join(' \u2190 ');
4915 }
4916
4917 /// Returns the parent chain from this element back to the root of the tree.
4918 ///
4919 /// Useful for debug display of a tree of Elements with only nodes in the path
4920 /// from the root to this Element expanded.
4921 List<Element> debugGetDiagnosticChain() {
4922 final List<Element> chain = <Element>[this];
4923 Element? node = _parent;
4924 while (node != null) {
4925 chain.add(node);
4926 node = node._parent;
4927 }
4928 return chain;
4929 }
4930
4931 @override
4932 void dispatchNotification(Notification notification) {
4933 _notificationTree?.dispatchNotification(notification);
4934 }
4935
4936 /// A short, textual description of this element.
4937 @override
4938 String toStringShort() => _widget?.toStringShort() ?? '${describeIdentity(this)}(DEFUNCT)';
4939
4940 @override
4941 DiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {
4942 return _ElementDiagnosticableTreeNode(
4943 name: name,
4944 value: this,
4945 style: style,
4946 );
4947 }
4948
4949 @override
4950 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
4951 super.debugFillProperties(properties);
4952 properties.defaultDiagnosticsTreeStyle= DiagnosticsTreeStyle.dense;
4953 if (_lifecycleState != _ElementLifecycle.initial) {
4954 properties.add(ObjectFlagProperty<int>('depth', depth, ifNull: 'no depth'));
4955 }
4956 properties.add(ObjectFlagProperty<Widget>('widget', _widget, ifNull: 'no widget'));
4957 properties.add(DiagnosticsProperty<Key>('key', _widget?.key, showName: false, defaultValue: null, level: DiagnosticLevel.hidden));
4958 _widget?.debugFillProperties(properties);
4959 properties.add(FlagProperty('dirty', value: dirty, ifTrue: 'dirty'));
4960 final Set<InheritedElement>? deps = _dependencies;
4961 if (deps != null && deps.isNotEmpty) {
4962 final List<InheritedElement> sortedDependencies = deps.toList()
4963 ..sort((InheritedElement a, InheritedElement b) =>
4964 a.toStringShort().compareTo(b.toStringShort()));
4965 final List<DiagnosticsNode> diagnosticsDependencies = sortedDependencies
4966 .map((InheritedElement element) => element.widget.toDiagnosticsNode(style: DiagnosticsTreeStyle.sparse))
4967 .toList();
4968 properties.add(DiagnosticsProperty<Set<InheritedElement>>('dependencies', deps, description: diagnosticsDependencies.toString()));
4969 }
4970 }
4971
4972 @override
4973 List<DiagnosticsNode> debugDescribeChildren() {
4974 final List<DiagnosticsNode> children = <DiagnosticsNode>[];
4975 visitChildren((Element child) {
4976 children.add(child.toDiagnosticsNode());
4977 });
4978 return children;
4979 }
4980
4981 /// Returns true if the element has been marked as needing rebuilding.
4982 ///
4983 /// The flag is true when the element is first created and after
4984 /// [markNeedsBuild] has been called. The flag is reset to false in the
4985 /// [performRebuild] implementation.
4986 bool get dirty => _dirty;
4987 bool _dirty = true;
4988
4989 // Whether this is in owner._dirtyElements. This is used to know whether we
4990 // should be adding the element back into the list when it's reactivated.
4991 bool _inDirtyList = false;
4992
4993 // Whether we've already built or not. Set in [rebuild].
4994 bool _debugBuiltOnce = false;
4995
4996 /// Marks the element as dirty and adds it to the global list of widgets to
4997 /// rebuild in the next frame.
4998 ///
4999 /// Since it is inefficient to build an element twice in one frame,
5000 /// applications and widgets should be structured so as to only mark
5001 /// widgets dirty during event handlers before the frame begins, not during
5002 /// the build itself.
5003 void markNeedsBuild() {
5004 assert(_lifecycleState != _ElementLifecycle.defunct);
5005 if (_lifecycleState != _ElementLifecycle.active) {
5006 return;
5007 }
5008 assert(owner != null);
5009 assert(_lifecycleState == _ElementLifecycle.active);
5010 assert(() {
5011 if (owner!._debugBuilding) {
5012 assert(owner!._debugCurrentBuildTarget != null);
5013 assert(owner!._debugStateLocked);
5014 if (_debugIsInScope(owner!._debugCurrentBuildTarget!)) {
5015 return true;
5016 }
5017 final List<DiagnosticsNode> information = <DiagnosticsNode>[
5018 ErrorSummary('setState() or markNeedsBuild() called during build.'),
5019 ErrorDescription(
5020 'This ${widget.runtimeType} widget cannot be marked as needing to build because the framework '
5021 'is already in the process of building widgets. A widget can be marked as '
5022 'needing to be built during the build phase only if one of its ancestors '
5023 'is currently building. This exception is allowed because the framework '
5024 'builds parent widgets before children, which means a dirty descendant '
5025 'will always be built. Otherwise, the framework might not visit this '
5026 'widget during this build phase.',
5027 ),
5028 describeElement('The widget on which setState() or markNeedsBuild() was called was'),
5029 ];
5030 if (owner!._debugCurrentBuildTarget != null) {
5031 information.add(owner!._debugCurrentBuildTarget!.describeWidget('The widget which was currently being built when the offending call was made was'));
5032 }
5033 throw FlutterError.fromParts(information);
5034 } else if (owner!._debugStateLocked) {
5035 throw FlutterError.fromParts(<DiagnosticsNode>[
5036 ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),
5037 ErrorDescription(
5038 'This ${widget.runtimeType} widget cannot be marked as needing to build '
5039 'because the framework is locked.',
5040 ),
5041 describeElement('The widget on which setState() or markNeedsBuild() was called was'),
5042 ]);
5043 }
5044 return true;
5045 }());
5046 if (dirty) {
5047 return;
5048 }
5049 _dirty = true;
5050 owner!.scheduleBuildFor(this);
5051 }
5052
5053 /// Cause the widget to update itself. In debug builds, also verify various
5054 /// invariants.
5055 ///
5056 /// Called by the [BuildOwner] when [BuildOwner.scheduleBuildFor] has been
5057 /// called to mark this element dirty, by [mount] when the element is first
5058 /// built, and by [update] when the widget has changed.
5059 ///
5060 /// The method will only rebuild if [dirty] is true. To rebuild regardless
5061 /// of the [dirty] flag, set `force` to true. Forcing a rebuild is convenient
5062 /// from [update], during which [dirty] is false.
5063 ///
5064 /// ## When rebuilds happen
5065 ///
5066 /// ### Terminology
5067 ///
5068 /// [Widget]s represent the configuration of [Element]s. Each [Element] has a
5069 /// widget, specified in [Element.widget]. The term "widget" is often used
5070 /// when strictly speaking "element" would be more correct.
5071 ///
5072 /// While an [Element] has a current [Widget], over time, that widget may be
5073 /// replaced by others. For example, the element backing a [ColoredBox] may
5074 /// first have as its widget a [ColoredBox] whose [ColoredBox.color] is blue,
5075 /// then later be given a new [ColoredBox] whose color is green.
5076 ///
5077 /// At any particular time, multiple [Element]s in the same tree may have the
5078 /// same [Widget]. For example, the same [ColoredBox] with the green color may
5079 /// be used in multiple places in the widget tree at the same time, each being
5080 /// backed by a different [Element].
5081 ///
5082 /// ### Marking an element dirty
5083 ///
5084 /// An [Element] can be marked dirty between frames. This can happen for various
5085 /// reasons, including the following:
5086 ///
5087 /// * The [State] of a [StatefulWidget] can cause its [Element] to be marked
5088 /// dirty by calling the [State.setState] method.
5089 ///
5090 /// * When an [InheritedWidget] changes, descendants that have previously
5091 /// subscribed to it will be marked dirty.
5092 ///
5093 /// * During a hot reload, every element is marked dirty (using [Element.reassemble]).
5094 ///
5095 /// ### Rebuilding
5096 ///
5097 /// Dirty elements are rebuilt during the next frame. Precisely how this is
5098 /// done depends on the kind of element. A [StatelessElement] rebuilds by
5099 /// using its widget's [StatelessWidget.build] method. A [StatefulElement]
5100 /// rebuilds by using its widget's state's [State.build] method. A
5101 /// [RenderObjectElement] rebuilds by updating its [RenderObject].
5102 ///
5103 /// In many cases, the end result of rebuilding is a single child widget
5104 /// or (for [MultiChildRenderObjectElement]s) a list of children widgets.
5105 ///
5106 /// These child widgets are used to update the [widget] property of the
5107 /// element's child (or children) elements. The new [Widget] is considered to
5108 /// correspond to an existing [Element] if it has the same [Type] and [Key].
5109 /// (In the case of [MultiChildRenderObjectElement]s, some effort is put into
5110 /// tracking widgets even when they change order; see
5111 /// [RenderObjectElement.updateChildren].)
5112 ///
5113 /// If there was no corresponding previous child, this results in a new
5114 /// [Element] being created (using [Widget.createElement]); that element is
5115 /// then itself built, recursively.
5116 ///
5117 /// If there was a child previously but the build did not provide a
5118 /// corresponding child to update it, then the old child is discarded (or, in
5119 /// cases involving [GlobalKey] reparenting, reused elsewhere in the element
5120 /// tree).
5121 ///
5122 /// The most common case, however, is that there was a corresponding previous
5123 /// child. This is handled by asking the child [Element] to update itself
5124 /// using the new child [Widget]. In the case of [StatefulElement]s, this
5125 /// is what triggers [State.didUpdateWidget].
5126 ///
5127 /// ### Not rebuilding
5128 ///
5129 /// Before an [Element] is told to update itself with a new [Widget], the old
5130 /// and new objects are compared using `operator ==`.
5131 ///
5132 /// In general, this is equivalent to doing a comparison using [identical] to
5133 /// see if the two objects are in fact the exact same instance. If they are,
5134 /// and if the element is not already marked dirty for other reasons, then the
5135 /// element skips updating itself as it can determine with certainty that
5136 /// there would be no value in updating itself or its descendants.
5137 ///
5138 /// It is strongly advised to avoid overriding `operator ==` on [Widget]
5139 /// objects. While doing so seems like it could improve performance, in
5140 /// practice, for non-leaf widgets, it results in O(N²) behavior. This is
5141 /// because by necessity the comparison would have to include comparing child
5142 /// widgets, and if those child widgets also implement `operator ==`, it
5143 /// ultimately results in a complete walk of the widget tree... which is then
5144 /// repeated at each level of the tree. In practice, just rebuilding is
5145 /// cheaper. (Additionally, if _any_ subclass of [Widget] used in an
5146 /// application implements `operator ==`, then the compiler cannot inline the
5147 /// comparison anywhere, because it has to treat the call as virtual just in
5148 /// case the instance happens to be one that has an overridden operator.)
5149 ///
5150 /// Instead, the best way to avoid unnecessary rebuilds is to cache the
5151 /// widgets that are returned from [State.build], so that each frame the same
5152 /// widgets are used until such time as they change. Several mechanisms exist
5153 /// to encourage this: `const` widgets, for example, are a form of automatic
5154 /// caching (if a widget is constructed using the `const` keyword, the same
5155 /// instance is returned each time it is constructed with the same arguments).
5156 ///
5157 /// Another example is the [AnimatedBuilder.child] property, which allows the
5158 /// non-animating parts of a subtree to remain static even as the
5159 /// [AnimatedBuilder.builder] callback recreates the other components.
5160 @pragma('vm:prefer-inline')
5161 void rebuild({bool force = false}) {
5162 assert(_lifecycleState != _ElementLifecycle.initial);
5163 if (_lifecycleState != _ElementLifecycle.active || (!_dirty && !force)) {
5164 return;
5165 }
5166 assert(() {
5167 debugOnRebuildDirtyWidget?.call(this, _debugBuiltOnce);
5168 if (debugPrintRebuildDirtyWidgets) {
5169 if (!_debugBuiltOnce) {
5170 debugPrint('Building $this');
5171 _debugBuiltOnce = true;
5172 } else {
5173 debugPrint('Rebuilding $this');
5174 }
5175 }
5176 return true;
5177 }());
5178 assert(_lifecycleState == _ElementLifecycle.active);
5179 assert(owner!._debugStateLocked);
5180 Element? debugPreviousBuildTarget;
5181 assert(() {
5182 debugPreviousBuildTarget = owner!._debugCurrentBuildTarget;
5183 owner!._debugCurrentBuildTarget = this;
5184 return true;
5185 }());
5186 try {
5187 performRebuild();
5188 } finally {
5189 assert(() {
5190 owner!._debugElementWasRebuilt(this);
5191 assert(owner!._debugCurrentBuildTarget == this);
5192 owner!._debugCurrentBuildTarget = debugPreviousBuildTarget;
5193 return true;
5194 }());
5195 }
5196 assert(!_dirty);
5197 }
5198
5199 /// Cause the widget to update itself.
5200 ///
5201 /// Called by [rebuild] after the appropriate checks have been made.
5202 ///
5203 /// The base implementation only clears the [dirty] flag.
5204 @protected
5205 @mustCallSuper
5206 void performRebuild() {
5207 _dirty = false;
5208 }
5209}
5210
5211class _ElementDiagnosticableTreeNode extends DiagnosticableTreeNode {
5212 _ElementDiagnosticableTreeNode({
5213 super.name,
5214 required Element super.value,
5215 required super.style,
5216 this.stateful = false,
5217 });
5218
5219 final bool stateful;
5220
5221 @override
5222 Map<String, Object?> toJsonMap(DiagnosticsSerializationDelegate delegate) {
5223 final Map<String, Object?> json = super.toJsonMap(delegate);
5224 final Element element = value as Element;
5225 if (!element.debugIsDefunct) {
5226 json['widgetRuntimeType'] = element.widget.runtimeType.toString();
5227 }
5228 json['stateful'] = stateful;
5229 return json;
5230 }
5231}
5232
5233/// Signature for the constructor that is called when an error occurs while
5234/// building a widget.
5235///
5236/// The argument provides information regarding the cause of the error.
5237///
5238/// See also:
5239///
5240/// * [ErrorWidget.builder], which can be set to override the default
5241/// [ErrorWidget] builder.
5242/// * [FlutterError.reportError], which is typically called with the same
5243/// [FlutterErrorDetails] object immediately prior to [ErrorWidget.builder]
5244/// being called.
5245typedef ErrorWidgetBuilder = Widget Function(FlutterErrorDetails details);
5246
5247/// A widget that renders an exception's message.
5248///
5249/// This widget is used when a build method fails, to help with determining
5250/// where the problem lies. Exceptions are also logged to the console, which you
5251/// can read using `flutter logs`. The console will also include additional
5252/// information such as the stack trace for the exception.
5253///
5254/// It is possible to override this widget.
5255///
5256/// {@tool dartpad}
5257/// This example shows how to override the standard error widget builder in release
5258/// mode, but use the standard one in debug mode.
5259///
5260/// The error occurs when you click the "Error Prone" button.
5261///
5262/// ** See code in examples/api/lib/widgets/framework/error_widget.0.dart **
5263/// {@end-tool}
5264///
5265/// See also:
5266///
5267/// * [FlutterError.onError], which can be set to a method that exits the
5268/// application if that is preferable to showing an error message.
5269/// * <https://flutter.dev/docs/testing/errors>, more information about error
5270/// handling in Flutter.
5271class ErrorWidget extends LeafRenderObjectWidget {
5272 /// Creates a widget that displays the given exception.
5273 ///
5274 /// The message will be the stringification of the given exception, unless
5275 /// computing that value itself throws an exception, in which case it will
5276 /// be the string "Error".
5277 ///
5278 /// If this object is inspected from an IDE or the devtools, and the original
5279 /// exception is a [FlutterError] object, the original exception itself will
5280 /// be shown in the inspection output.
5281 ErrorWidget(Object exception)
5282 : message = _stringify(exception),
5283 _flutterError = exception is FlutterError ? exception : null,
5284 super(key: UniqueKey());
5285
5286 /// Creates a widget that displays the given error message.
5287 ///
5288 /// An explicit [FlutterError] can be provided to be reported to inspection
5289 /// tools. It need not match the message.
5290 ErrorWidget.withDetails({ this.message = '', FlutterError? error })
5291 : _flutterError = error,
5292 super(key: UniqueKey());
5293
5294 /// The configurable factory for [ErrorWidget].
5295 ///
5296 /// When an error occurs while building a widget, the broken widget is
5297 /// replaced by the widget returned by this function. By default, an
5298 /// [ErrorWidget] is returned.
5299 ///
5300 /// The system is typically in an unstable state when this function is called.
5301 /// An exception has just been thrown in the middle of build (and possibly
5302 /// layout), so surrounding widgets and render objects may be in a rather
5303 /// fragile state. The framework itself (especially the [BuildOwner]) may also
5304 /// be confused, and additional exceptions are quite likely to be thrown.
5305 ///
5306 /// Because of this, it is highly recommended that the widget returned from
5307 /// this function perform the least amount of work possible. A
5308 /// [LeafRenderObjectWidget] is the best choice, especially one that
5309 /// corresponds to a [RenderBox] that can handle the most absurd of incoming
5310 /// constraints. The default constructor maps to a [RenderErrorBox].
5311 ///
5312 /// The default behavior is to show the exception's message in debug mode,
5313 /// and to show nothing but a gray background in release builds.
5314 ///
5315 /// See also:
5316 ///
5317 /// * [FlutterError.onError], which is typically called with the same
5318 /// [FlutterErrorDetails] object immediately prior to this callback being
5319 /// invoked, and which can also be configured to control how errors are
5320 /// reported.
5321 /// * <https://flutter.dev/docs/testing/errors>, more information about error
5322 /// handling in Flutter.
5323 static ErrorWidgetBuilder builder = _defaultErrorWidgetBuilder;
5324
5325 static Widget _defaultErrorWidgetBuilder(FlutterErrorDetails details) {
5326 String message = '';
5327 assert(() {
5328 message = '${_stringify(details.exception)}\nSee also: https://flutter.dev/docs/testing/errors';
5329 return true;
5330 }());
5331 final Object exception = details.exception;
5332 return ErrorWidget.withDetails(message: message, error: exception is FlutterError ? exception : null);
5333 }
5334
5335 static String _stringify(Object? exception) {
5336 try {
5337 return exception.toString();
5338 } catch (error) {
5339 // If we get here, it means things have really gone off the rails, and we're better
5340 // off just returning a simple string and letting the developer find out what the
5341 // root cause of all their problems are by looking at the console logs.
5342 }
5343 return 'Error';
5344 }
5345
5346 /// The message to display.
5347 final String message;
5348 final FlutterError? _flutterError;
5349
5350 @override
5351 RenderBox createRenderObject(BuildContext context) => RenderErrorBox(message);
5352
5353 @override
5354 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
5355 super.debugFillProperties(properties);
5356 if (_flutterError == null) {
5357 properties.add(StringProperty('message', message, quoted: false));
5358 } else {
5359 properties.add(_flutterError.toDiagnosticsNode(style: DiagnosticsTreeStyle.whitespace));
5360 }
5361 }
5362}
5363
5364/// Signature for a function that creates a widget, e.g. [StatelessWidget.build]
5365/// or [State.build].
5366///
5367/// Used by [Builder.builder], [OverlayEntry.builder], etc.
5368///
5369/// See also:
5370///
5371/// * [IndexedWidgetBuilder], which is similar but also takes an index.
5372/// * [TransitionBuilder], which is similar but also takes a child.
5373/// * [ValueWidgetBuilder], which is similar but takes a value and a child.
5374typedef WidgetBuilder = Widget Function(BuildContext context);
5375
5376/// Signature for a function that creates a widget for a given index, e.g., in a
5377/// list.
5378///
5379/// Used by [ListView.builder] and other APIs that use lazily-generated widgets.
5380///
5381/// See also:
5382///
5383/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5384/// * [TransitionBuilder], which is similar but also takes a child.
5385/// * [NullableIndexedWidgetBuilder], which is similar but may return null.
5386typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
5387
5388/// Signature for a function that creates a widget for a given index, e.g., in a
5389/// list, but may return null.
5390///
5391/// Used by [SliverChildBuilderDelegate.builder] and other APIs that
5392/// use lazily-generated widgets where the child count is not known
5393/// ahead of time.
5394///
5395/// Unlike most builders, this callback can return null, indicating the index
5396/// is out of range. Whether and when this is valid depends on the semantics
5397/// of the builder. For example, [SliverChildBuilderDelegate.builder] returns
5398/// null when the index is out of range, where the range is defined by the
5399/// [SliverChildBuilderDelegate.childCount]; so in that case the `index`
5400/// parameter's value may determine whether returning null is valid or not.
5401///
5402/// See also:
5403///
5404/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5405/// * [TransitionBuilder], which is similar but also takes a child.
5406/// * [IndexedWidgetBuilder], which is similar but not nullable.
5407typedef NullableIndexedWidgetBuilder = Widget? Function(BuildContext context, int index);
5408
5409/// A builder that builds a widget given a child.
5410///
5411/// The child should typically be part of the returned widget tree.
5412///
5413/// Used by [AnimatedBuilder.builder], [ListenableBuilder.builder],
5414/// [WidgetsApp.builder], and [MaterialApp.builder].
5415///
5416/// See also:
5417///
5418/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
5419/// * [IndexedWidgetBuilder], which is similar but also takes an index.
5420/// * [ValueWidgetBuilder], which is similar but takes a value and a child.
5421typedef TransitionBuilder = Widget Function(BuildContext context, Widget? child);
5422
5423/// An [Element] that composes other [Element]s.
5424///
5425/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
5426/// [RenderObject]s indirectly by creating other [Element]s.
5427///
5428/// Contrast with [RenderObjectElement].
5429abstract class ComponentElement extends Element {
5430 /// Creates an element that uses the given widget as its configuration.
5431 ComponentElement(super.widget);
5432
5433 Element? _child;
5434
5435 bool _debugDoingBuild = false;
5436 @override
5437 bool get debugDoingBuild => _debugDoingBuild;
5438
5439 @override
5440 Element? get renderObjectAttachingChild => _child;
5441
5442 @override
5443 void mount(Element? parent, Object? newSlot) {
5444 super.mount(parent, newSlot);
5445 assert(_child == null);
5446 assert(_lifecycleState == _ElementLifecycle.active);
5447 _firstBuild();
5448 assert(_child != null);
5449 }
5450
5451 void _firstBuild() {
5452 // StatefulElement overrides this to also call state.didChangeDependencies.
5453 rebuild(); // This eventually calls performRebuild.
5454 }
5455
5456 /// Calls the [StatelessWidget.build] method of the [StatelessWidget] object
5457 /// (for stateless widgets) or the [State.build] method of the [State] object
5458 /// (for stateful widgets) and then updates the widget tree.
5459 ///
5460 /// Called automatically during [mount] to generate the first build, and by
5461 /// [rebuild] when the element needs updating.
5462 @override
5463 @pragma('vm:notify-debugger-on-exception')
5464 void performRebuild() {
5465 Widget? built;
5466 try {
5467 assert(() {
5468 _debugDoingBuild = true;
5469 return true;
5470 }());
5471 built = build();
5472 assert(() {
5473 _debugDoingBuild = false;
5474 return true;
5475 }());
5476 debugWidgetBuilderValue(widget, built);
5477 } catch (e, stack) {
5478 _debugDoingBuild = false;
5479 built = ErrorWidget.builder(
5480 _reportException(
5481 ErrorDescription('building $this'),
5482 e,
5483 stack,
5484 informationCollector: () => <DiagnosticsNode>[
5485 if (kDebugMode)
5486 DiagnosticsDebugCreator(DebugCreator(this)),
5487 ],
5488 ),
5489 );
5490 } finally {
5491 // We delay marking the element as clean until after calling build() so
5492 // that attempts to markNeedsBuild() during build() will be ignored.
5493 super.performRebuild(); // clears the "dirty" flag
5494 }
5495 try {
5496 _child = updateChild(_child, built, slot);
5497 assert(_child != null);
5498 } catch (e, stack) {
5499 built = ErrorWidget.builder(
5500 _reportException(
5501 ErrorDescription('building $this'),
5502 e,
5503 stack,
5504 informationCollector: () => <DiagnosticsNode>[<