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