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

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com