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