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