framework.dart 245 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:async';
6
import 'dart:collection';
7
import 'dart:developer';
8

9
import 'package:flutter/foundation.dart';
10 11 12
import 'package:flutter/rendering.dart';

import 'debug.dart';
13
import 'focus_manager.dart';
14
import 'inherited_model.dart';
15

16
export 'dart:ui' show hashValues, hashList;
17

18 19 20 21 22 23 24
export 'package:flutter/foundation.dart' show
  immutable,
  mustCallSuper,
  optionalTypeArgs,
  protected,
  required,
  visibleForTesting;
25
export 'package:flutter/foundation.dart' show FlutterError, ErrorSummary, ErrorDescription, ErrorHint, debugPrint, debugPrintStack;
26
export 'package:flutter/foundation.dart' show VoidCallback, ValueChanged, ValueGetter, ValueSetter;
27
export 'package:flutter/foundation.dart' show DiagnosticsNode, DiagnosticLevel;
28
export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;
29
export 'package:flutter/rendering.dart' show RenderObject, RenderBox, debugDumpRenderTree, debugDumpLayerTree;
30

31 32 33 34 35 36 37 38 39
// Examples can assume:
// BuildContext context;
// void setState(VoidCallback fn) { }

// Examples can assume:
// abstract class RenderFrogJar extends RenderObject { }
// abstract class FrogJar extends RenderObjectWidget { }
// abstract class FrogJarParentData extends ParentData { Size size; }

Hixie's avatar
Hixie committed
40 41
// KEYS

42
/// A key that is only equal to itself.
43 44 45
///
/// This cannot be created with a const constructor because that implies that
/// all instantiated keys would be the same instance and therefore not be unique.
Hixie's avatar
Hixie committed
46
class UniqueKey extends LocalKey {
47
  /// Creates a key that is equal only to itself.
48 49 50 51
  ///
  /// The key cannot be created with a const constructor because that implies
  /// that all instantiated keys would be the same instance and therefore not
  /// be unique.
52
  // ignore: prefer_const_constructors_in_immutables , never use const for this class
53
  UniqueKey();
54 55

  @override
56
  String toString() => '[#${shortHash(this)}]';
Hixie's avatar
Hixie committed
57 58
}

59
/// A key that takes its identity from the object used as its value.
60
///
61 62
/// Used to tie the identity of a widget to the identity of an object used to
/// generate that widget.
63
///
64 65 66 67 68
/// See also:
///
///  * [Key], the base class for all keys.
///  * The discussion at [Widget.key] for more information about how widgets use
///    keys.
Hixie's avatar
Hixie committed
69
class ObjectKey extends LocalKey {
70
  /// Creates a key that uses [identical] on [value] for its [operator==].
Hixie's avatar
Hixie committed
71
  const ObjectKey(this.value);
72

73
  /// The object whose identity is used by this key's [operator==].
74
  final Object value;
75 76

  @override
77
  bool operator ==(Object other) {
Ian Hickson's avatar
Ian Hickson committed
78
    if (other.runtimeType != runtimeType)
Hixie's avatar
Hixie committed
79
      return false;
80 81
    return other is ObjectKey
        && identical(other.value, value);
Hixie's avatar
Hixie committed
82
  }
83 84

  @override
Ian Hickson's avatar
Ian Hickson committed
85
  int get hashCode => hashValues(runtimeType, identityHashCode(value));
86 87

  @override
Ian Hickson's avatar
Ian Hickson committed
88 89
  String toString() {
    if (runtimeType == ObjectKey)
90
      return '[${describeIdentity(value)}]';
91
    return '[${objectRuntimeType(this, 'ObjectKey')} ${describeIdentity(value)}]';
Ian Hickson's avatar
Ian Hickson committed
92
  }
93 94
}

95
/// A key that is unique across the entire app.
96
///
97
/// Global keys uniquely identify elements. Global keys provide access to other
98 99
/// objects that are associated with those elements, such as [BuildContext].
/// For [StatefulWidget]s, global keys also provide access to [State].
100 101 102 103 104 105 106
///
/// Widgets that have global keys reparent their subtrees when they are moved
/// from one location in the tree to another location in the tree. In order to
/// reparent its subtree, a widget must arrive at its new location in the tree
/// in the same animation frame in which it was removed from its old location in
/// the tree.
///
107
/// Global keys are relatively expensive. If you don't need any of the features
108 109
/// listed above, consider using a [Key], [ValueKey], [ObjectKey], or
/// [UniqueKey] instead.
110 111 112
///
/// You cannot simultaneously include two widgets in the tree with the same
/// global key. Attempting to do so will assert at runtime.
113
///
114 115 116 117
/// See also:
///
///  * The discussion at [Widget.key] for more information about how widgets use
///    keys.
pq's avatar
pq committed
118
@optionalTypeArgs
119
abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
120 121
  /// Creates a [LabeledGlobalKey], which is a [GlobalKey] with a label used for
  /// debugging.
122 123 124
  ///
  /// The label is purely for debugging and not used for comparing the identity
  /// of the key.
125
  factory GlobalKey({ String debugLabel }) => LabeledGlobalKey<T>(debugLabel);
126

127 128
  /// Creates a global key without a label.
  ///
129
  /// Used by subclasses because the factory constructor shadows the implicit
130
  /// constructor.
131
  const GlobalKey.constructor() : super.empty();
Ian Hickson's avatar
Ian Hickson committed
132

133
  static final Map<GlobalKey, Element> _registry = <GlobalKey, Element>{};
134
  static final Set<Element> _debugIllFatedElements = HashSet<Element>();
135
  // This map keeps track which child reserves the global key with the parent.
136 137 138 139 140 141 142 143 144 145 146 147 148
  // Parent, child -> global key.
  // This provides us a way to remove old reservation while parent rebuilds the
  // child in the same slot.
  static final Map<Element, Map<Element, GlobalKey>> _debugReservations = <Element, Map<Element, GlobalKey>>{};

  static void _debugRemoveReservationFor(Element parent, Element child) {
    assert(() {
      assert(parent != null);
      assert(child != null);
      _debugReservations[parent]?.remove(child);
      return true;
    }());
  }
149

150
  void _register(Element element) {
151 152
    assert(() {
      if (_registry.containsKey(this)) {
153 154 155 156
        assert(element.widget != null);
        assert(_registry[this].widget != null);
        assert(element.widget.runtimeType != _registry[this].widget.runtimeType);
        _debugIllFatedElements.add(_registry[this]);
157 158
      }
      return true;
159
    }());
160
    _registry[this] = element;
161 162
  }

163
  void _unregister(Element element) {
164
    assert(() {
165 166 167 168
      if (_registry.containsKey(this) && _registry[this] != element) {
        assert(element.widget != null);
        assert(_registry[this].widget != null);
        assert(element.widget.runtimeType != _registry[this].widget.runtimeType);
169 170
      }
      return true;
171
    }());
172
    if (_registry[this] == element)
173 174 175
      _registry.remove(this);
  }

176
  void _debugReserveFor(Element parent, Element child) {
177 178
    assert(() {
      assert(parent != null);
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
      assert(child != null);
      _debugReservations[parent] ??= <Element, GlobalKey>{};
      _debugReservations[parent][child] = this;
      return true;
    }());
  }

  static void _debugVerifyGlobalKeyReservation() {
    assert(() {
      final Map<GlobalKey, Element> keyToParent = <GlobalKey, Element>{};
      _debugReservations.forEach((Element parent, Map<Element, GlobalKey> chidToKey) {
        // We ignore parent that are detached.
        if (parent.renderObject?.attached == false)
          return;
        chidToKey.forEach((Element child, GlobalKey key) {
          // If parent = null, the node is deactivated by its parent and is
          // not re-attached to other part of the tree. We should ignore this
          // node.
          if (child._parent == null)
            return;
          // It is possible the same key registers to the same parent twice
          // with different children. That is illegal, but it is not in the
          // scope of this check. Such error will be detected in
          // _debugVerifyIllFatedPopulation or
          // _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.
          if (keyToParent.containsKey(key) && keyToParent[key] != parent) {
            // We have duplication reservations for the same global key.
            final Element older = keyToParent[key];
            final Element newer = parent;
            FlutterError error;
            if (older.toString() != newer.toString()) {
              error = FlutterError.fromParts(<DiagnosticsNode>[
                ErrorSummary('Multiple widgets used the same GlobalKey.'),
                ErrorDescription(
                  'The key $key was used by multiple widgets. The parents of those widgets were:\n'
                    '- ${older.toString()}\n'
                    '- ${newer.toString()}\n'
                    'A GlobalKey can only be specified on one widget at a time in the widget tree.'
                ),
              ]);
            } else {
              error = FlutterError.fromParts(<DiagnosticsNode>[
                ErrorSummary('Multiple widgets used the same GlobalKey.'),
                ErrorDescription(
                  'The key $key was used by multiple widgets. The parents of those widgets were '
                    'different widgets that both had the following description:\n'
                    '  ${parent.toString()}\n'
                    'A GlobalKey can only be specified on one widget at a time in the widget tree.'
                ),
              ]);
            }
            // Fix the tree by removing the duplicated child from one of its
            // parents to resolve the duplicated key issue. This allows us to
            // tear down the tree during testing without producing additional
            // misleading exceptions.
            if (child._parent != older) {
              older.visitChildren((Element currentChild) {
                if (currentChild == child)
                  older.forgetChild(child);
              });
            }
            if (child._parent != newer) {
              newer.visitChildren((Element currentChild) {
                if (currentChild == child)
                  newer.forgetChild(child);
              });
            }
            throw error;
          } else {
            keyToParent[key] = parent;
          }
        });
      });
      _debugReservations.clear();
253
      return true;
254
    }());
255 256 257 258 259
  }

  static void _debugVerifyIllFatedPopulation() {
    assert(() {
      Map<GlobalKey, Set<Element>> duplicates;
260
      for (final Element element in _debugIllFatedElements) {
261 262 263 264
        if (element._debugLifecycleState != _ElementLifecycle.defunct) {
          assert(element != null);
          assert(element.widget != null);
          assert(element.widget.key != null);
265
          final GlobalKey key = element.widget.key as GlobalKey;
266 267
          assert(_registry.containsKey(key));
          duplicates ??= <GlobalKey, Set<Element>>{};
268 269
          // Uses ordered set to produce consistent error message.
          final Set<Element> elements = duplicates.putIfAbsent(key, () => LinkedHashSet<Element>());
270 271 272 273 274 275
          elements.add(element);
          elements.add(_registry[key]);
        }
      }
      _debugIllFatedElements.clear();
      if (duplicates != null) {
276 277
        final List<DiagnosticsNode> information = <DiagnosticsNode>[];
        information.add(ErrorSummary('Multiple widgets used the same GlobalKey.'));
278
        for (final GlobalKey key in duplicates.keys) {
279
          final Set<Element> elements = duplicates[key];
280 281 282 283 284 285
          // TODO(jacobr): this will omit the '- ' before each widget name and
          // use the more standard whitespace style instead. Please let me know
          // if the '- ' style is a feature we want to maintain and we can add
          // another tree style that supports it. I also see '* ' in some places
          // so it would be nice to unify and normalize.
          information.add(Element.describeElements('The key $key was used by ${elements.length} widgets', elements));
286
        }
287 288
        information.add(ErrorDescription('A GlobalKey can only be specified on one widget at a time in the widget tree.'));
        throw FlutterError.fromParts(information);
289 290
      }
      return true;
291
    }());
292 293
  }

294
  Element get _currentElement => _registry[this];
295 296 297 298 299

  /// The build context in which the widget with this key builds.
  ///
  /// The current context is null if there is no widget in the tree that matches
  /// this global key.
300
  BuildContext get currentContext => _currentElement;
301 302 303 304 305

  /// The widget in the tree that currently has this global key.
  ///
  /// The current widget is null if there is no widget in the tree that matches
  /// this global key.
306
  Widget get currentWidget => _currentElement?.widget;
307 308 309 310 311

  /// The [State] for the widget in the tree that currently has this global key.
  ///
  /// The current state is null if (1) there is no widget in the tree that
  /// matches this global key, (2) that widget is not a [StatefulWidget], or the
312
  /// associated [State] object is not a subtype of `T`.
313
  T get currentState {
314
    final Element element = _currentElement;
315
    if (element is StatefulElement) {
316 317
      final StatefulElement statefulElement = element;
      final State state = statefulElement.state;
318 319
      if (state is T)
        return state;
320
    }
321
    return null;
322
  }
323 324
}

325 326 327 328
/// A global key with a debugging label.
///
/// The debug label is useful for documentation and for debugging. The label
/// does not affect the key's identity.
329
@optionalTypeArgs
330
class LabeledGlobalKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
331 332 333
  /// Creates a global key with a debugging label.
  ///
  /// The label does not affect the key's identity.
334
  // ignore: prefer_const_constructors_in_immutables , never use const for this class
335
  LabeledGlobalKey(this._debugLabel) : super.constructor();
336

337
  final String _debugLabel;
338 339

  @override
Ian Hickson's avatar
Ian Hickson committed
340
  String toString() {
341
    final String label = _debugLabel != null ? ' $_debugLabel' : '';
342
    if (runtimeType == LabeledGlobalKey)
343 344
      return '[GlobalKey#${shortHash(this)}$label]';
    return '[${describeIdentity(this)}$label]';
Ian Hickson's avatar
Ian Hickson committed
345
  }
346 347
}

348
/// A global key that takes its identity from the object used as its value.
349
///
350 351
/// Used to tie the identity of a widget to the identity of an object used to
/// generate that widget.
Ian Hickson's avatar
Ian Hickson committed
352
///
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
/// If the object is not private, then it is possible that collisions will occur
/// where independent widgets will reuse the same object as their
/// [GlobalObjectKey] value in a different part of the tree, leading to a global
/// key conflict. To avoid this problem, create a private [GlobalObjectKey]
/// subclass, as in:
///
/// ```dart
/// class _MyKey extends GlobalObjectKey {
///   const _MyKey(Object value) : super(value);
/// }
/// ```
///
/// Since the [runtimeType] of the key is part of its identity, this will
/// prevent clashes with other [GlobalObjectKey]s even if they have the same
/// value.
///
Ian Hickson's avatar
Ian Hickson committed
369
/// Any [GlobalObjectKey] created for the same value will match.
370 371
@optionalTypeArgs
class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
372
  /// Creates a global key that uses [identical] on [value] for its [operator==].
Adam Barth's avatar
Adam Barth committed
373
  const GlobalObjectKey(this.value) : super.constructor();
374 375

  /// The object whose identity is used by this key's [operator==].
376
  final Object value;
377 378

  @override
379
  bool operator ==(Object other) {
Ian Hickson's avatar
Ian Hickson committed
380
    if (other.runtimeType != runtimeType)
Hixie's avatar
Hixie committed
381
      return false;
382 383
    return other is GlobalObjectKey<T>
        && identical(other.value, value);
Hixie's avatar
Hixie committed
384
  }
385 386

  @override
387
  int get hashCode => identityHashCode(value);
388 389

  @override
390
  String toString() {
391 392
    String selfType = objectRuntimeType(this, 'GlobalObjectKey');
    // The runtimeType string of a GlobalObjectKey() returns 'GlobalObjectKey<State<StatefulWidget>>'
393 394 395 396 397 398 399 400
    // because GlobalObjectKey is instantiated to its bounds. To avoid cluttering the output
    // we remove the suffix.
    const String suffix = '<State<StatefulWidget>>';
    if (selfType.endsWith(suffix)) {
      selfType = selfType.substring(0, selfType.length - suffix.length);
    }
    return '[$selfType ${describeIdentity(value)}]';
  }
Eric Seidel's avatar
Eric Seidel committed
401 402
}

403 404 405 406 407 408 409 410
/// This class is a work-around for the "is" operator not accepting a variable value as its right operand.
///
/// This class is deprecated. It will be deleted soon.
// TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
@Deprecated(
  'TypeMatcher has been deprecated because it is no longer used in framework(only in deprecated methods). '
  'This feature was deprecated after v1.12.1.'
)
pq's avatar
pq committed
411
@optionalTypeArgs
Ian Hickson's avatar
Ian Hickson committed
412
class TypeMatcher<T> {
413
  /// Creates a type matcher for the given type parameter.
Ian Hickson's avatar
Ian Hickson committed
414
  const TypeMatcher();
415

416
  /// Returns true if the given object is of type `T`.
Ian Hickson's avatar
Ian Hickson committed
417 418
  bool check(dynamic object) => object is T;
}
419

420 421 422 423 424 425
/// Describes the configuration for an [Element].
///
/// Widgets are the central class hierarchy in the Flutter framework. A widget
/// is an immutable description of part of a user interface. Widgets can be
/// inflated into elements, which manage the underlying render tree.
///
426 427 428 429 430
/// Widgets themselves have no mutable state (all their fields must be final).
/// If you wish to associate mutable state with a widget, consider using a
/// [StatefulWidget], which creates a [State] object (via
/// [StatefulWidget.createState]) whenever it is inflated into an element and
/// incorporated into the tree.
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
///
/// A given widget can be included in the tree zero or more times. In particular
/// a given widget can be placed in the tree multiple times. Each time a widget
/// is placed in the tree, it is inflated into an [Element], which means a
/// widget that is incorporated into the tree multiple times will be inflated
/// multiple times.
///
/// The [key] property controls how one widget replaces another widget in the
/// tree. If the [runtimeType] and [key] properties of the two widgets are
/// [operator==], respectively, then the new widget replaces the old widget by
/// updating the underlying element (i.e., by calling [Element.update] with the
/// new widget). Otherwise, the old element is removed from the tree, the new
/// widget is inflated into an element, and the new element is inserted into the
/// tree.
///
/// See also:
///
448 449 450 451 452 453
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
///  * [InheritedWidget], for widgets that introduce ambient state that can
///    be read by descendant widgets.
///  * [StatelessWidget], for widgets that always build the same way given a
///    particular configuration and ambient state.
454
@immutable
455
abstract class Widget extends DiagnosticableTree {
456
  /// Initializes [key] for subclasses.
457
  const Widget({ this.key });
458 459 460 461 462 463 464 465 466

  /// Controls how one widget replaces another widget in the tree.
  ///
  /// If the [runtimeType] and [key] properties of the two widgets are
  /// [operator==], respectively, then the new widget replaces the old widget by
  /// updating the underlying element (i.e., by calling [Element.update] with the
  /// new widget). Otherwise, the old element is removed from the tree, the new
  /// widget is inflated into an element, and the new element is inserted into the
  /// tree.
467
  ///
468 469 470 471 472 473 474 475 476 477
  /// In addition, using a [GlobalKey] as the widget's [key] allows the element
  /// to be moved around the tree (changing parent) without losing state. When a
  /// new widget is found (its key and type do not match a previous widget in
  /// the same location), but there was a widget with that same global key
  /// elsewhere in the tree in the previous frame, then that widget's element is
  /// moved to the new location.
  ///
  /// Generally, a widget that is the only child of another widget does not need
  /// an explicit key.
  ///
478 479 480
  /// See also:
  ///
  ///  * The discussions at [Key] and [GlobalKey].
481
  final Key key;
482

483
  /// Inflates this configuration to a concrete instance.
484 485 486 487 488 489
  ///
  /// A given widget can be included in the tree zero or more times. In particular
  /// a given widget can be placed in the tree multiple times. Each time a widget
  /// is placed in the tree, it is inflated into an [Element], which means a
  /// widget that is incorporated into the tree multiple times will be inflated
  /// multiple times.
490
  @protected
491
  Element createElement();
492

493
  /// A short, textual description of this widget.
494
  @override
495
  String toStringShort() {
496 497
    final String type = objectRuntimeType(this, 'Widget');
    return key == null ? type : '$type-$key';
498 499
  }

500
  @override
501 502 503
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
504
  }
505

506 507
  @override
  @nonVirtual
508
  bool operator ==(Object other) => super == other;
509 510 511 512

  @override
  @nonVirtual
  int get hashCode => super.hashCode;
513

514 515 516 517 518 519
  /// Whether the `newWidget` can be used to update an [Element] that currently
  /// has the `oldWidget` as its configuration.
  ///
  /// An element that uses a given widget as its configuration can be updated to
  /// use another widget as its configuration if, and only if, the two widgets
  /// have [runtimeType] and [key] properties that are [operator==].
520 521 522 523
  ///
  /// If the widgets have no key (their key is null), then they are considered a
  /// match if they have the same type, even if their children are completely
  /// different.
524
  static bool canUpdate(Widget oldWidget, Widget newWidget) {
525 526
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
527
  }
528 529 530 531 532 533 534 535 536 537

  // Return a numeric encoding of the specific `Widget` concrete subtype.
  // This is used in `Element.updateChild` to determine if a hot reload modified the
  // superclass of a mounted element's configuration. The encoding of each `Widget`
  // must match the corresponding `Element` encoding in `Element._debugConcreteSubtype`.
  static int _debugConcreteSubtype(Widget widget) {
    return widget is StatefulWidget ? 1 :
           widget is StatelessWidget ? 2 :
           0;
    }
538
}
539

540 541 542 543 544 545
/// A widget that does not require mutable state.
///
/// A stateless widget is a widget that describes part of the user interface by
/// building a constellation of other widgets that describe the user interface
/// more concretely. The building process continues recursively until the
/// description of the user interface is fully concrete (e.g., consists
546
/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
547
///
548 549
/// {@youtube 560 315 https://www.youtube.com/watch?v=wE7khGHVkYY}
///
550 551 552 553 554 555 556
/// Stateless widget are useful when the part of the user interface you are
/// describing does not depend on anything other than the configuration
/// information in the object itself and the [BuildContext] in which the widget
/// is inflated. For compositions that can change dynamically, e.g. due to
/// having an internal clock-driven state, or depending on some system state,
/// consider using [StatefulWidget].
///
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
/// ## Performance considerations
///
/// The [build] method of a stateless widget is typically only called in three
/// situations: the first time the widget is inserted in the tree, when the
/// widget's parent changes its configuration, and when an [InheritedWidget] it
/// depends on changes.
///
/// If a widget's parent will regularly change the widget's configuration, or if
/// it depends on inherited widgets that frequently change, then it is important
/// to optimize the performance of the [build] method to maintain a fluid
/// rendering performance.
///
/// There are several techniques one can use to minimize the impact of
/// rebuilding a stateless widget:
///
///  * Minimize the number of nodes transitively created by the build method and
///    any widgets it creates. For example, instead of an elaborate arrangement
///    of [Row]s, [Column]s, [Padding]s, and [SizedBox]es to position a single
///    child in a particularly fancy manner, consider using just an [Align] or a
///    [CustomSingleChildLayout]. Instead of an intricate layering of multiple
///    [Container]s and with [Decoration]s to draw just the right graphical
///    effect, consider a single [CustomPaint] widget.
///
///  * Use `const` widgets where possible, and provide a `const` constructor for
///    the widget so that users of the widget can also do so.
///
///  * Consider refactoring the stateless widget into a stateful widget so that
///    it can use some of the techniques described at [StatefulWidget], such as
///    caching common parts of subtrees and using [GlobalKey]s when changing the
///    tree structure.
///
///  * If the widget is likely to get rebuilt frequently due to the use of
///    [InheritedWidget]s, consider refactoring the stateless widget into
///    multiple widgets, with the parts of the tree that change being pushed to
///    the leaves. For example instead of building a tree with four widgets, the
///    inner-most widget depending on the [Theme], consider factoring out the
///    part of the build function that builds the inner-most widget into its own
///    widget, so that only the inner-most widget needs to be rebuilt when the
///    theme changes.
///
597
/// {@tool snippet}
598
///
599 600 601 602
/// The following is a skeleton of a stateless widget subclass called `GreenFrog`.
///
/// Normally, widgets have more constructor arguments, each of which corresponds
/// to a `final` property.
603 604 605 606 607 608 609
///
/// ```dart
/// class GreenFrog extends StatelessWidget {
///   const GreenFrog({ Key key }) : super(key: key);
///
///   @override
///   Widget build(BuildContext context) {
610
///     return Container(color: const Color(0xFF2DBD3A));
611 612 613
///   }
/// }
/// ```
614
/// {@end-tool}
615
///
616
/// {@tool snippet}
617
///
618 619
/// This next example shows the more generic widget `Frog` which can be given
/// a color and a child:
620 621 622 623 624
///
/// ```dart
/// class Frog extends StatelessWidget {
///   const Frog({
///     Key key,
625
///     this.color = const Color(0xFF2DBD3A),
626 627 628 629 630 631 632 633
///     this.child,
///   }) : super(key: key);
///
///   final Color color;
///   final Widget child;
///
///   @override
///   Widget build(BuildContext context) {
634
///     return Container(color: color, child: child);
635 636 637
///   }
/// }
/// ```
638
/// {@end-tool}
639 640 641 642 643 644
///
/// By convention, widget constructors only use named arguments. Named arguments
/// can be marked as required using [@required]. Also by convention, the first
/// argument is [key], and the last argument is `child`, `children`, or the
/// equivalent.
///
645 646
/// See also:
///
647 648 649 650
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
///  * [InheritedWidget], for widgets that introduce ambient state that can
///    be read by descendant widgets.
651
abstract class StatelessWidget extends Widget {
652
  /// Initializes [key] for subclasses.
653
  const StatelessWidget({ Key key }) : super(key: key);
654

655 656
  /// Creates a [StatelessElement] to manage this widget's location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
657
  /// It is uncommon for subclasses to override this method.
658
  @override
659
  StatelessElement createElement() => StatelessElement(this);
660

661 662
  /// Describes the part of the user interface represented by this widget.
  ///
Adam Barth's avatar
Adam Barth committed
663
  /// The framework calls this method when this widget is inserted into the
664 665
  /// tree in a given [BuildContext] and when the dependencies of this widget
  /// change (e.g., an [InheritedWidget] referenced by this widget changes).
666
  ///
667
  /// The framework replaces the subtree below this widget with the widget
Adam Barth's avatar
Adam Barth committed
668
  /// returned by this method, either by updating the existing subtree or by
669
  /// removing the subtree and inflating a new subtree, depending on whether the
Adam Barth's avatar
Adam Barth committed
670 671
  /// widget returned by this method can update the root of the existing
  /// subtree, as determined by calling [Widget.canUpdate].
672
  ///
Adam Barth's avatar
Adam Barth committed
673
  /// Typically implementations return a newly created constellation of widgets
674 675 676 677 678 679
  /// that are configured with information from this widget's constructor and
  /// from the given [BuildContext].
  ///
  /// The given [BuildContext] contains information about the location in the
  /// tree at which this widget is being built. For example, the context
  /// provides the set of inherited widgets for this location in the tree. A
680 681 682
  /// given widget might be built with multiple different [BuildContext]
  /// arguments over time if the widget is moved around the tree or if the
  /// widget is inserted into the tree in multiple places at once.
683 684 685 686 687 688
  ///
  /// The implementation of this method must only depend on:
  ///
  /// * the fields of the widget, which themselves must not change over time,
  ///   and
  /// * any ambient state obtained from the `context` using
689
  ///   [BuildContext.dependOnInheritedWidgetOfExactType].
690 691 692
  ///
  /// If a widget's [build] method is to depend on anything else, use a
  /// [StatefulWidget] instead.
693 694 695
  ///
  /// See also:
  ///
696
  ///  * [StatelessWidget], which contains the discussion on performance considerations.
697
  @protected
698 699
  Widget build(BuildContext context);
}
700

701 702
/// A widget that has mutable state.
///
703 704 705 706
/// State is information that (1) can be read synchronously when the widget is
/// built and (2) might change during the lifetime of the widget. It is the
/// responsibility of the widget implementer to ensure that the [State] is
/// promptly notified when such state changes, using [State.setState].
707 708 709 710 711
///
/// A stateful widget is a widget that describes part of the user interface by
/// building a constellation of other widgets that describe the user interface
/// more concretely. The building process continues recursively until the
/// description of the user interface is fully concrete (e.g., consists
712
/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
713
///
714
/// Stateful widgets are useful when the part of the user interface you are
715 716 717 718 719 720
/// describing can change dynamically, e.g. due to having an internal
/// clock-driven state, or depending on some system state. For compositions that
/// depend only on the configuration information in the object itself and the
/// [BuildContext] in which the widget is inflated, consider using
/// [StatelessWidget].
///
721 722
/// {@youtube 560 315 https://www.youtube.com/watch?v=AqCMFXEmf3w}
///
723
/// [StatefulWidget] instances themselves are immutable and store their mutable
724 725 726 727 728 729
/// state either in separate [State] objects that are created by the
/// [createState] method, or in objects to which that [State] subscribes, for
/// example [Stream] or [ChangeNotifier] objects, to which references are stored
/// in final fields on the [StatefulWidget] itself.
///
/// The framework calls [createState] whenever it inflates a
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
/// [StatefulWidget], which means that multiple [State] objects might be
/// associated with the same [StatefulWidget] if that widget has been inserted
/// into the tree in multiple places. Similarly, if a [StatefulWidget] is
/// removed from the tree and later inserted in to the tree again, the framework
/// will call [createState] again to create a fresh [State] object, simplifying
/// the lifecycle of [State] objects.
///
/// A [StatefulWidget] keeps the same [State] object when moving from one
/// location in the tree to another if its creator used a [GlobalKey] for its
/// [key]. Because a widget with a [GlobalKey] can be used in at most one
/// location in the tree, a widget that uses a [GlobalKey] has at most one
/// associated element. The framework takes advantage of this property when
/// moving a widget with a global key from one location in the tree to another
/// by grafting the (unique) subtree associated with that widget from the old
/// location to the new location (instead of recreating the subtree at the new
/// location). The [State] objects associated with [StatefulWidget] are grafted
/// along with the rest of the subtree, which means the [State] object is reused
/// (instead of being recreated) in the new location. However, in order to be
748
/// eligible for grafting, the widget must be inserted into the new location in
749 750
/// the same animation frame in which it was removed from the old location.
///
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
/// ## Performance considerations
///
/// There are two primary categories of [StatefulWidget]s.
///
/// The first is one which allocates resources in [State.initState] and disposes
/// of them in [State.dispose], but which does not depend on [InheritedWidget]s
/// or call [State.setState]. Such widgets are commonly used at the root of an
/// application or page, and communicate with subwidgets via [ChangeNotifier]s,
/// [Stream]s, or other such objects. Stateful widgets following such a pattern
/// are relatively cheap (in terms of CPU and GPU cycles), because they are
/// built once then never update. They can, therefore, have somewhat complicated
/// and deep build methods.
///
/// The second category is widgets that use [State.setState] or depend on
/// [InheritedWidget]s. These will typically rebuild many times during the
766
/// application's lifetime, and it is therefore important to minimize the impact
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
/// of rebuilding such a widget. (They may also use [State.initState] or
/// [State.didChangeDependencies] and allocate resources, but the important part
/// is that they rebuild.)
///
/// There are several techniques one can use to minimize the impact of
/// rebuilding a stateful widget:
///
///  * Push the state to the leaves. For example, if your page has a ticking
///    clock, rather than putting the state at the top of the page and
///    rebuilding the entire page each time the clock ticks, create a dedicated
///    clock widget that only updates itself.
///
///  * Minimize the number of nodes transitively created by the build method and
///    any widgets it creates. Ideally, a stateful widget would only create a
///    single widget, and that widget would be a [RenderObjectWidget].
///    (Obviously this isn't always practical, but the closer a widget gets to
///    this ideal, the more efficient it will be.)
///
///  * If a subtree does not change, cache the widget that represents that
///    subtree and re-use it each time it can be used. It is massively more
///    efficient for a widget to be re-used than for a new (but
///    identically-configured) widget to be created. Factoring out the stateful
///    part into a widget that takes a child argument is a common way of doing
///    this.
///
///  * Use `const` widgets where possible. (This is equivalent to caching a
///    widget and re-using it.)
///
///  * Avoid changing the depth of any created subtrees or changing the type of
///    any widgets in the subtree. For example, rather than returning either the
///    child or the child wrapped in an [IgnorePointer], always wrap the child
///    widget in an [IgnorePointer] and control the [IgnorePointer.ignoring]
///    property. This is because changing the depth of the subtree requires
///    rebuilding, laying out, and painting the entire subtree, whereas just
///    changing the property will require the least possible change to the
///    render tree (in the case of [IgnorePointer], for example, no layout or
///    repaint is necessary at all).
///
///  * If the depth must be changed for some reason, consider wrapping the
///    common parts of the subtrees in widgets that have a [GlobalKey] that
///    remains consistent for the life of the stateful widget. (The
///    [KeyedSubtree] widget may be useful for this purpose if no other widget
///    can conveniently be assigned the key.)
///
811
/// {@tool snippet}
812
///
813 814 815 816 817
/// This is a skeleton of a stateful widget subclass called `YellowBird`.
///
/// In this example. the [State] has no actual state. State is normally
/// represented as private member fields. Also, normally widgets have more
/// constructor arguments, each of which corresponds to a `final` property.
818 819
///
/// ```dart
820 821
/// class YellowBird extends StatefulWidget {
///   const YellowBird({ Key key }) : super(key: key);
822 823
///
///   @override
824
///   _YellowBirdState createState() => _YellowBirdState();
825 826
/// }
///
827
/// class _YellowBirdState extends State<YellowBird> {
828 829
///   @override
///   Widget build(BuildContext context) {
830
///     return Container(color: const Color(0xFFFFE306));
831 832 833
///   }
/// }
/// ```
834
/// {@end-tool}
835
/// {@tool snippet}
836
///
837
/// This example shows the more generic widget `Bird` which can be given a
838 839 840 841
/// color and a child, and which has some internal state with a method that
/// can be called to mutate it:
///
/// ```dart
842 843
/// class Bird extends StatefulWidget {
///   const Bird({
844
///     Key key,
845
///     this.color = const Color(0xFFFFE306),
846 847 848 849 850 851
///     this.child,
///   }) : super(key: key);
///
///   final Color color;
///   final Widget child;
///
852
///   _BirdState createState() => _BirdState();
853 854
/// }
///
855
/// class _BirdState extends State<Bird> {
856 857 858 859 860 861 862 863
///   double _size = 1.0;
///
///   void grow() {
///     setState(() { _size += 0.1; });
///   }
///
///   @override
///   Widget build(BuildContext context) {
864
///     return Container(
865
///       color: widget.color,
866
///       transform: Matrix4.diagonal3Values(_size, _size, 1.0),
867 868 869 870 871
///       child: widget.child,
///     );
///   }
/// }
/// ```
872
/// {@end-tool}
873 874 875 876 877 878
///
/// By convention, widget constructors only use named arguments. Named arguments
/// can be marked as required using [@required]. Also by convention, the first
/// argument is [key], and the last argument is `child`, `children`, or the
/// equivalent.
///
879 880
/// See also:
///
881 882 883 884 885
///  * [State], where the logic behind a [StatefulWidget] is hosted.
///  * [StatelessWidget], for widgets that always build the same way given a
///    particular configuration and ambient state.
///  * [InheritedWidget], for widgets that introduce ambient state that can
///    be read by descendant widgets.
886
abstract class StatefulWidget extends Widget {
887
  /// Initializes [key] for subclasses.
888
  const StatefulWidget({ Key key }) : super(key: key);
889

890 891
  /// Creates a [StatefulElement] to manage this widget's location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
892
  /// It is uncommon for subclasses to override this method.
893
  @override
894
  StatefulElement createElement() => StatefulElement(this);
895

896 897
  /// Creates the mutable state for this widget at a given location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
898
  /// Subclasses should override this method to return a newly created
899 900 901 902
  /// instance of their associated [State] subclass:
  ///
  /// ```dart
  /// @override
903
  /// _MyState createState() => _MyState();
904
  /// ```
905
  ///
Adam Barth's avatar
Adam Barth committed
906
  /// The framework can call this method multiple times over the lifetime of
907 908 909 910 911 912
  /// a [StatefulWidget]. For example, if the widget is inserted into the tree
  /// in multiple locations, the framework will create a separate [State] object
  /// for each location. Similarly, if the widget is removed from the tree and
  /// later inserted into the tree again, the framework will call [createState]
  /// again to create a fresh [State] object, simplifying the lifecycle of
  /// [State] objects.
913
  @protected
914 915
  State createState();
}
916

917
/// Tracks the lifecycle of [State] objects when asserts are enabled.
918
enum _StateLifecycle {
919 920
  /// The [State] object has been created. [State.initState] is called at this
  /// time.
921
  created,
922

Adam Barth's avatar
Adam Barth committed
923
  /// The [State.initState] method has been called but the [State] object is
924
  /// not yet ready to build. [State.didChangeDependencies] is called at this time.
925
  initialized,
926 927 928

  /// The [State] object is ready to build and [State.dispose] has not yet been
  /// called.
929
  ready,
930

Adam Barth's avatar
Adam Barth committed
931
  /// The [State.dispose] method has been called and the [State] object is
932
  /// no longer able to build.
933 934
  defunct,
}
935

936
/// The signature of [State.setState] functions.
937
typedef StateSetter = void Function(VoidCallback fn);
938

939
/// The logic and internal state for a [StatefulWidget].
Adam Barth's avatar
Adam Barth committed
940
///
941 942 943 944
/// State is information that (1) can be read synchronously when the widget is
/// built and (2) might change during the lifetime of the widget. It is the
/// responsibility of the widget implementer to ensure that the [State] is
/// promptly notified when such state changes, using [State.setState].
Adam Barth's avatar
Adam Barth committed
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
///
/// [State] objects are created by the framework by calling the
/// [StatefulWidget.createState] method when inflating a [StatefulWidget] to
/// insert it into the tree. Because a given [StatefulWidget] instance can be
/// inflated multiple times (e.g., the widget is incorporated into the tree in
/// multiple places at once), there might be more than one [State] object
/// associated with a given [StatefulWidget] instance. Similarly, if a
/// [StatefulWidget] is removed from the tree and later inserted in to the tree
/// again, the framework will call [StatefulWidget.createState] again to create
/// a fresh [State] object, simplifying the lifecycle of [State] objects.
///
/// [State] objects have the following lifecycle:
///
///  * The framework creates a [State] object by calling
///    [StatefulWidget.createState].
///  * The newly created [State] object is associated with a [BuildContext].
///    This association is permanent: the [State] object will never change its
///    [BuildContext]. However, the [BuildContext] itself can be moved around
///    the tree along with its subtree. At this point, the [State] object is
///    considered [mounted].
///  * The framework calls [initState]. Subclasses of [State] should override
///    [initState] to perform one-time initialization that depends on the
///    [BuildContext] or the widget, which are available as the [context] and
968
///    [widget] properties, respectively, when the [initState] method is
Adam Barth's avatar
Adam Barth committed
969
///    called.
970 971
///  * The framework calls [didChangeDependencies]. Subclasses of [State] should
///    override [didChangeDependencies] to perform initialization involving
972
///    [InheritedWidget]s. If [BuildContext.dependOnInheritedWidgetOfExactType] is
973
///    called, the [didChangeDependencies] method will be called again if the
974
///    inherited widgets subsequently change or if the widget moves in the tree.
Adam Barth's avatar
Adam Barth committed
975 976 977
///  * At this point, the [State] object is fully initialized and the framework
///    might call its [build] method any number of times to obtain a
///    description of the user interface for this subtree. [State] objects can
lyrachord's avatar
lyrachord committed
978
///    spontaneously request to rebuild their subtree by callings their
Adam Barth's avatar
Adam Barth committed
979 980 981 982 983
///    [setState] method, which indicates that some of their internal state
///    has changed in a way that might impact the user interface in this
///    subtree.
///  * During this time, a parent widget might rebuild and request that this
///    location in the tree update to display a new widget with the same
Ian Hickson's avatar
Ian Hickson committed
984 985 986 987
///    [runtimeType] and [Widget.key]. When this happens, the framework will
///    update the [widget] property to refer to the new widget and then call the
///    [didUpdateWidget] method with the previous widget as an argument. [State]
///    objects should override [didUpdateWidget] to respond to changes in their
988
///    associated widget (e.g., to start implicit animations). The framework
Ian Hickson's avatar
Ian Hickson committed
989 990
///    always calls [build] after calling [didUpdateWidget], which means any
///    calls to [setState] in [didUpdateWidget] are redundant.
991 992 993 994
///  * During development, if a hot reload occurs (whether initiated from the
///    command line `flutter` tool by pressing `r`, or from an IDE), the
///    [reassemble] method is called. This provides an opportunity to
///    reinitialize any data that was prepared in the [initState] method.
Adam Barth's avatar
Adam Barth committed
995 996
///  * If the subtree containing the [State] object is removed from the tree
///    (e.g., because the parent built a widget with a different [runtimeType]
Ian Hickson's avatar
Ian Hickson committed
997
///    or [Widget.key]), the framework calls the [deactivate] method. Subclasses
Adam Barth's avatar
Adam Barth committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
///    should override this method to clean up any links between this object
///    and other elements in the tree (e.g. if you have provided an ancestor
///    with a pointer to a descendant's [RenderObject]).
///  * At this point, the framework might reinsert this subtree into another
///    part of the tree. If that happens, the framework will ensure that it
///    calls [build] to give the [State] object a chance to adapt to its new
///    location in the tree. If the framework does reinsert this subtree, it
///    will do so before the end of the animation frame in which the subtree was
///    removed from the tree. For this reason, [State] objects can defer
///    releasing most resources until the framework calls their [dispose]
///    method.
///  * If the framework does not reinsert this subtree by the end of the current
1010
///    animation frame, the framework will call [dispose], which indicates that
Adam Barth's avatar
Adam Barth committed
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
///    this [State] object will never build again. Subclasses should override
///    this method to release any resources retained by this object (e.g.,
///    stop any active animations).
///  * After the framework calls [dispose], the [State] object is considered
///    unmounted and the [mounted] property is false. It is an error to call
///    [setState] at this point. This stage of the lifecycle is terminal: there
///    is no way to remount a [State] object that has been disposed.
///
/// See also:
///
1021 1022
///  * [StatefulWidget], where the current configuration of a [State] is hosted,
///    and whose documentation has sample code for [State].
1023 1024 1025 1026
///  * [StatelessWidget], for widgets that always build the same way given a
///    particular configuration and ambient state.
///  * [InheritedWidget], for widgets that introduce ambient state that can
///    be read by descendant widgets.
1027
///  * [Widget], for an overview of widgets in general.
pq's avatar
pq committed
1028
@optionalTypeArgs
1029
abstract class State<T extends StatefulWidget> with Diagnosticable {
Adam Barth's avatar
Adam Barth committed
1030 1031 1032 1033 1034
  /// The current configuration.
  ///
  /// A [State] object's configuration is the corresponding [StatefulWidget]
  /// instance. This property is initialized by the framework before calling
  /// [initState]. If the parent updates this location in the tree to a new
1035 1036 1037 1038
  /// widget with the same [runtimeType] and [Widget.key] as the current
  /// configuration, the framework will update this property to refer to the new
  /// widget and then call [didUpdateWidget], passing the old configuration as
  /// an argument.
1039 1040 1041
  T get widget => _widget;
  T _widget;

Adam Barth's avatar
Adam Barth committed
1042 1043 1044 1045
  /// The current stage in the lifecycle for this state object.
  ///
  /// This field is used by the framework when asserts are enabled to verify
  /// that [State] objects move through their lifecycle in an orderly fashion.
1046
  _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
1047

Adam Barth's avatar
Adam Barth committed
1048 1049
  /// Verifies that the [State] that was created is one that expects to be
  /// created for that particular [Widget].
1050
  bool _debugTypesAreRight(Widget widget) => widget is T;
1051

Adam Barth's avatar
Adam Barth committed
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
  /// The location in the tree where this widget builds.
  ///
  /// The framework associates [State] objects with a [BuildContext] after
  /// creating them with [StatefulWidget.createState] and before calling
  /// [initState]. The association is permanent: the [State] object will never
  /// change its [BuildContext]. However, the [BuildContext] itself can be moved
  /// around the tree.
  ///
  /// After calling [dispose], the framework severs the [State] object's
  /// connection with the [BuildContext].
1062
  BuildContext get context => _element;
1063
  StatefulElement _element;
1064

Adam Barth's avatar
Adam Barth committed
1065 1066 1067 1068 1069 1070 1071 1072 1073
  /// Whether this [State] object is currently in a tree.
  ///
  /// After creating a [State] object and before calling [initState], the
  /// framework "mounts" the [State] object by associating it with a
  /// [BuildContext]. The [State] object remains mounted until the framework
  /// calls [dispose], after which time the framework will never ask the [State]
  /// object to [build] again.
  ///
  /// It is an error to call [setState] unless [mounted] is true.
1074
  bool get mounted => _element != null;
1075

Adam Barth's avatar
Adam Barth committed
1076 1077
  /// Called when this object is inserted into the tree.
  ///
1078 1079 1080
  /// The framework will call this method exactly once for each [State] object
  /// it creates.
  ///
Adam Barth's avatar
Adam Barth committed
1081 1082
  /// Override this method to perform initialization that depends on the
  /// location at which this object was inserted into the tree (i.e., [context])
1083
  /// or on the widget used to configure this object (i.e., [widget]).
Adam Barth's avatar
Adam Barth committed
1084
  ///
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
  /// {@template flutter.widgets.subscriptions}
  /// If a [State]'s [build] method depends on an object that can itself
  /// change state, for example a [ChangeNotifier] or [Stream], or some
  /// other object to which one can subscribe to receive notifications, then
  /// be sure to subscribe and unsubscribe properly in [initState],
  /// [didUpdateWidget], and [dispose]:
  ///
  ///  * In [initState], subscribe to the object.
  ///  * In [didUpdateWidget] unsubscribe from the old object and subscribe
  ///    to the new one if the updated widget configuration requires
  ///    replacing the object.
  ///  * In [dispose], unsubscribe from the object.
1097
  ///
1098
  /// {@endtemplate}
1099
  ///
1100
  /// You cannot use [BuildContext.dependOnInheritedWidgetOfExactType] from this
1101
  /// method. However, [didChangeDependencies] will be called immediately
1102
  /// following this method, and [BuildContext.dependOnInheritedWidgetOfExactType] can
1103 1104
  /// be used there.
  ///
1105 1106
  /// If you override this, make sure your method starts with a call to
  /// super.initState().
1107
  @protected
1108
  @mustCallSuper
1109 1110
  void initState() {
    assert(_debugLifecycleState == _StateLifecycle.created);
1111
  }
1112

1113
  /// Called whenever the widget configuration changes.
Adam Barth's avatar
Adam Barth committed
1114 1115
  ///
  /// If the parent widget rebuilds and request that this location in the tree
1116 1117
  /// update to display a new widget with the same [runtimeType] and
  /// [Widget.key], the framework will update the [widget] property of this
1118
  /// [State] object to refer to the new widget and then call this method
1119
  /// with the previous widget as an argument.
Adam Barth's avatar
Adam Barth committed
1120
  ///
1121 1122
  /// Override this method to respond when the [widget] changes (e.g., to start
  /// implicit animations).
Adam Barth's avatar
Adam Barth committed
1123
  ///
1124 1125
  /// The framework always calls [build] after calling [didUpdateWidget], which
  /// means any calls to [setState] in [didUpdateWidget] are redundant.
Adam Barth's avatar
Adam Barth committed
1126
  ///
1127
  /// {@macro flutter.widgets.subscriptions}
1128
  ///
Adam Barth's avatar
Adam Barth committed
1129
  /// If you override this, make sure your method starts with a call to
1130
  /// super.didUpdateWidget(oldWidget).
1131
  @mustCallSuper
1132
  @protected
1133 1134
  void didUpdateWidget(covariant T oldWidget) { }

1135
  /// {@macro flutter.widgets.reassemble}
1136 1137
  ///
  /// In addition to this method being invoked, it is guaranteed that the
1138
  /// [build] method will be invoked when a reassemble is signaled. Most
1139 1140 1141 1142
  /// widgets therefore do not need to do anything in the [reassemble] method.
  ///
  /// See also:
  ///
1143
  ///  * [Element.reassemble]
1144
  ///  * [BindingBase.reassembleApplication]
1145
  ///  * [Image], which uses this to reload images.
1146 1147 1148 1149
  @protected
  @mustCallSuper
  void reassemble() { }

Adam Barth's avatar
Adam Barth committed
1150 1151 1152 1153
  /// Notify the framework that the internal state of this object has changed.
  ///
  /// Whenever you change the internal state of a [State] object, make the
  /// change in a function that you pass to [setState]:
1154
  ///
1155
  /// ```dart
aoisensi's avatar
aoisensi committed
1156
  /// setState(() { _myState = newValue; });
1157
  /// ```
1158
  ///
1159 1160 1161 1162
  /// The provided callback is immediately called synchronously. It must not
  /// return a future (the callback cannot be `async`), since then it would be
  /// unclear when the state was actually being set.
  ///
Adam Barth's avatar
Adam Barth committed
1163 1164 1165 1166 1167 1168 1169 1170 1171
  /// Calling [setState] notifies the framework that the internal state of this
  /// object has changed in a way that might impact the user interface in this
  /// subtree, which causes the framework to schedule a [build] for this [State]
  /// object.
  ///
  /// If you just change the state directly without calling [setState], the
  /// framework might not schedule a [build] and the user interface for this
  /// subtree might not be updated to reflect the new state.
  ///
1172 1173 1174 1175 1176 1177 1178
  /// Generally it is recommended that the `setState` method only be used to
  /// wrap the actual changes to the state, not any computation that might be
  /// associated with the change. For example, here a value used by the [build]
  /// function is incremented, and then the change is written to disk, but only
  /// the increment is wrapped in the `setState`:
  ///
  /// ```dart
1179
  /// Future<void> _incrementCounter() async {
1180 1181 1182
  ///   setState(() {
  ///     _counter++;
  ///   });
1183 1184
  ///   Directory directory = await getApplicationDocumentsDirectory();
  ///   final String dirName = directory.path;
1185
  ///   await File('$dir/counter.txt').writeAsString('$_counter');
1186 1187 1188
  /// }
  /// ```
  ///
Adam Barth's avatar
Adam Barth committed
1189 1190 1191
  /// It is an error to call this method after the framework calls [dispose].
  /// You can determine whether it is legal to call this method by checking
  /// whether the [mounted] property is true.
1192
  @protected
1193
  void setState(VoidCallback fn) {
1194
    assert(fn != null);
1195 1196
    assert(() {
      if (_debugLifecycleState == _StateLifecycle.defunct) {
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called after dispose(): $this'),
          ErrorDescription(
            'This error happens if you call setState() on a State object for a widget that '
            'no longer appears in the widget tree (e.g., whose parent widget no longer '
            'includes the widget in its build). This error can occur when code calls '
            'setState() from a timer or an animation callback.'
          ),
          ErrorHint(
            'The preferred solution is '
            'to cancel the timer or stop listening to the animation in the dispose() '
            'callback. Another solution is to check the "mounted" property of this '
            'object before calling setState() to ensure the object is still in the '
            'tree.'
          ),
          ErrorHint(
            'This error might indicate a memory leak if setState() is being called '
            'because another object is retaining a reference to this State object '
            'after it has been removed from the tree. To avoid memory leaks, '
            'consider breaking the reference to this object during dispose().'
          ),
        ]);
1219
      }
1220
      if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
1221 1222 1223 1224
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called in constructor: $this'),
          ErrorHint(
            'This happens when you call setState() on a State object for a widget that '
1225
            "hasn't been inserted into the widget tree yet. It is not necessary to call "
1226 1227
            'setState() in the constructor, since the state is already assumed to be dirty '
            'when it is initially created.'
1228
          ),
1229
        ]);
1230
      }
1231
      return true;
1232
    }());
1233
    final dynamic result = fn() as dynamic;
1234 1235
    assert(() {
      if (result is Future) {
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() callback argument returned a Future.'),
          ErrorDescription(
            'The setState() method on $this was called with a closure or method that '
            'returned a Future. Maybe it is marked as "async".'
          ),
          ErrorHint(
            'Instead of performing asynchronous work inside a call to setState(), first '
            'execute the work (without updating the widget state), and then synchronously '
           'update the state inside a call to setState().'
1246
          ),
1247
        ]);
1248 1249 1250 1251
      }
      // We ignore other types of return values so that you can do things like:
      //   setState(() => x = 3);
      return true;
1252
    }());
1253
    _element.markNeedsBuild();
1254
  }
1255

1256 1257
  /// Called when this object is removed from the tree.
  ///
Adam Barth's avatar
Adam Barth committed
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
  /// The framework calls this method whenever it removes this [State] object
  /// from the tree. In some cases, the framework will reinsert the [State]
  /// object into another part of the tree (e.g., if the subtree containing this
  /// [State] object is grafted from one location in the tree to another). If
  /// that happens, the framework will ensure that it calls [build] to give the
  /// [State] object a chance to adapt to its new location in the tree. If
  /// the framework does reinsert this subtree, it will do so before the end of
  /// the animation frame in which the subtree was removed from the tree. For
  /// this reason, [State] objects can defer releasing most resources until the
  /// framework calls their [dispose] method.
  ///
  /// Subclasses should override this method to clean up any links between
  /// this object and other elements in the tree (e.g. if you have provided an
  /// ancestor with a pointer to a descendant's [RenderObject]).
  ///
  /// If you override this, make sure to end your method with a call to
  /// super.deactivate().
1275
  ///
1276 1277 1278 1279
  /// See also:
  ///
  ///  * [dispose], which is called after [deactivate] if the widget is removed
  ///    from the tree permanently.
1280
  @protected
1281
  @mustCallSuper
1282 1283 1284
  void deactivate() { }

  /// Called when this object is removed from the tree permanently.
Adam Barth's avatar
Adam Barth committed
1285 1286 1287 1288 1289 1290 1291 1292 1293
  ///
  /// The framework calls this method when this [State] object will never
  /// build again. After the framework calls [dispose], the [State] object is
  /// considered unmounted and the [mounted] property is false. It is an error
  /// to call [setState] at this point. This stage of the lifecycle is terminal:
  /// there is no way to remount a [State] object that has been disposed.
  ///
  /// Subclasses should override this method to release any resources retained
  /// by this object (e.g., stop any active animations).
1294
  ///
1295
  /// {@macro flutter.widgets.subscriptions}
1296
  ///
1297 1298
  /// If you override this, make sure to end your method with a call to
  /// super.dispose().
1299
  ///
1300 1301 1302
  /// See also:
  ///
  ///  * [deactivate], which is called prior to [dispose].
1303
  @protected
1304
  @mustCallSuper
1305 1306
  void dispose() {
    assert(_debugLifecycleState == _StateLifecycle.ready);
1307 1308 1309 1310
    assert(() {
      _debugLifecycleState = _StateLifecycle.defunct;
      return true;
    }());
1311 1312
  }

Adam Barth's avatar
Adam Barth committed
1313
  /// Describes the part of the user interface represented by this widget.
1314
  ///
Adam Barth's avatar
Adam Barth committed
1315
  /// The framework calls this method in a number of different situations:
1316
  ///
Adam Barth's avatar
Adam Barth committed
1317
  ///  * After calling [initState].
1318
  ///  * After calling [didUpdateWidget].
Adam Barth's avatar
Adam Barth committed
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
  ///  * After receiving a call to [setState].
  ///  * After a dependency of this [State] object changes (e.g., an
  ///    [InheritedWidget] referenced by the previous [build] changes).
  ///  * After calling [deactivate] and then reinserting the [State] object into
  ///    the tree at another location.
  ///
  /// The framework replaces the subtree below this widget with the widget
  /// returned by this method, either by updating the existing subtree or by
  /// removing the subtree and inflating a new subtree, depending on whether the
  /// widget returned by this method can update the root of the existing
  /// subtree, as determined by calling [Widget.canUpdate].
  ///
  /// Typically implementations return a newly created constellation of widgets
  /// that are configured with information from this widget's constructor, the
  /// given [BuildContext], and the internal state of this [State] object.
  ///
  /// The given [BuildContext] contains information about the location in the
  /// tree at which this widget is being built. For example, the context
  /// provides the set of inherited widgets for this location in the tree. The
  /// [BuildContext] argument is always the same as the [context] property of
  /// this [State] object and will remain the same for the lifetime of this
  /// object. The [BuildContext] argument is provided redundantly here so that
  /// this method matches the signature for a [WidgetBuilder].
1342 1343 1344 1345 1346 1347
  ///
  /// ## Design discussion
  ///
  /// ### Why is the [build] method on [State], and not [StatefulWidget]?
  ///
  /// Putting a `Widget build(BuildContext context)` method on [State] rather
1348 1349
  /// than putting a `Widget build(BuildContext context, State state)` method
  /// on [StatefulWidget] gives developers more flexibility when subclassing
1350 1351 1352 1353
  /// [StatefulWidget].
  ///
  /// For example, [AnimatedWidget] is a subclass of [StatefulWidget] that
  /// introduces an abstract `Widget build(BuildContext context)` method for its
1354
  /// subclasses to implement. If [StatefulWidget] already had a [build] method
1355 1356 1357 1358 1359
  /// that took a [State] argument, [AnimatedWidget] would be forced to provide
  /// its [State] object to subclasses even though its [State] object is an
  /// internal implementation detail of [AnimatedWidget].
  ///
  /// Conceptually, [StatelessWidget] could also be implemented as a subclass of
1360
  /// [StatefulWidget] in a similar manner. If the [build] method were on
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
  /// [StatefulWidget] rather than [State], that would not be possible anymore.
  ///
  /// Putting the [build] function on [State] rather than [StatefulWidget] also
  /// helps avoid a category of bugs related to closures implicitly capturing
  /// `this`. If you defined a closure in a [build] function on a
  /// [StatefulWidget], that closure would implicitly capture `this`, which is
  /// the current widget instance, and would have the (immutable) fields of that
  /// instance in scope:
  ///
  /// ```dart
  /// class MyButton extends StatefulWidget {
  ///   ...
  ///   final Color color;
  ///
  ///   @override
  ///   Widget build(BuildContext context, MyButtonState state) {
  ///     ... () { print("color: $color"); } ...
  ///   }
  /// }
  /// ```
  ///
  /// For example, suppose the parent builds `MyButton` with `color` being blue,
1383 1384
  /// the `$color` in the print function refers to blue, as expected. Now,
  /// suppose the parent rebuilds `MyButton` with green. The closure created by
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
  /// the first build still implicitly refers to the original widget and the
  /// `$color` still prints blue even through the widget has been updated to
  /// green.
  ///
  /// In contrast, with the [build] function on the [State] object, closures
  /// created during [build] implicitly capture the [State] instance instead of
  /// the widget instance:
  ///
  /// ```dart
  /// class MyButtonState extends State<MyButton> {
  ///   ...
  ///   @override
  ///   Widget build(BuildContext context) {
1398
  ///     ... () { print("color: ${widget.color}"); } ...
1399 1400 1401 1402 1403 1404
  ///   }
  /// }
  /// ```
  ///
  /// Now when the parent rebuilds `MyButton` with green, the closure created by
  /// the first build still refers to [State] object, which is preserved across
1405 1406
  /// rebuilds, but the framework has updated that [State] object's [widget]
  /// property to refer to the new `MyButton` instance and `${widget.color}`
1407
  /// prints green, as expected.
1408 1409 1410
  ///
  /// See also:
  ///
1411
  ///  * [StatefulWidget], which contains the discussion on performance considerations.
1412
  @protected
1413
  Widget build(BuildContext context);
1414

1415
  /// Called when a dependency of this [State] object changes.
Adam Barth's avatar
Adam Barth committed
1416 1417 1418 1419 1420
  ///
  /// For example, if the previous call to [build] referenced an
  /// [InheritedWidget] that later changed, the framework would call this
  /// method to notify this object about the change.
  ///
1421
  /// This method is also called immediately after [initState]. It is safe to
1422
  /// call [BuildContext.dependOnInheritedWidgetOfExactType] from this method.
1423
  ///
Adam Barth's avatar
Adam Barth committed
1424 1425 1426 1427 1428
  /// Subclasses rarely override this method because the framework always
  /// calls [build] after a dependency changes. Some subclasses do override
  /// this method because they need to do some expensive work (e.g., network
  /// fetches) when their dependencies change, and that work would be too
  /// expensive to do for every build.
1429
  @protected
1430
  @mustCallSuper
1431
  void didChangeDependencies() { }
1432

1433
  @override
1434 1435
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
Hixie's avatar
Hixie committed
1436
    assert(() {
1437
      properties.add(EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));
Hixie's avatar
Hixie committed
1438
      return true;
1439
    }());
1440 1441
    properties.add(ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
    properties.add(ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));
1442
  }
1443
}
1444

1445 1446
/// A widget that has a child widget provided to it, instead of building a new
/// widget.
1447 1448 1449
///
/// Useful as a base class for other widgets, such as [InheritedWidget] and
/// [ParentDataWidget].
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
///
/// See also:
///
///  * [InheritedWidget], for widgets that introduce ambient state that can
///    be read by descendant widgets.
///  * [ParentDataWidget], for widgets that populate the
///    [RenderObject.parentData] slot of their child's [RenderObject] to
///    configure the parent widget's layout.
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
///  * [StatelessWidget], for widgets that always build the same way given a
///    particular configuration and ambient state.
///  * [Widget], for an overview of widgets in general.
1463 1464
abstract class ProxyWidget extends Widget {
  /// Creates a widget that has exactly one child widget.
1465
  const ProxyWidget({ Key key, @required this.child }) : super(key: key);
1466

1467
  /// The widget below this widget in the tree.
1468
  ///
1469 1470 1471 1472 1473
  /// {@template flutter.widgets.child}
  /// This widget can only have one child. To lay out multiple children, let this
  /// widget's child be a widget such as [Row], [Column], or [Stack], which have a
  /// `children` property, and then provide the children to that widget.
  /// {@endtemplate}
1474
  final Widget child;
1475 1476
}

1477 1478 1479 1480 1481 1482 1483
/// Base class for widgets that hook [ParentData] information to children of
/// [RenderObjectWidget]s.
///
/// This can be used to provide per-child configuration for
/// [RenderObjectWidget]s with more than one child. For example, [Stack] uses
/// the [Positioned] parent data widget to position each child.
///
1484 1485
/// A [ParentDataWidget] is specific to a particular kind of [ParentData]. That
/// class is `T`, the [ParentData] type argument.
1486
///
1487
/// {@tool snippet}
1488 1489 1490 1491 1492
///
/// This example shows how you would build a [ParentDataWidget] to configure a
/// `FrogJar` widget's children by specifying a [Size] for each one.
///
/// ```dart
1493
/// class FrogSize extends ParentDataWidget<FrogJarParentData> {
1494
///   FrogSize({
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
///     Key key,
///     @required this.size,
///     @required Widget child,
///   }) : assert(child != null),
///        assert(size != null),
///        super(key: key, child: child);
///
///   final Size size;
///
///   @override
///   void applyParentData(RenderObject renderObject) {
///     final FrogJarParentData parentData = renderObject.parentData;
///     if (parentData.size != size) {
///       parentData.size = size;
///       final RenderFrogJar targetParent = renderObject.parent;
///       targetParent.markNeedsLayout();
///     }
///   }
1513 1514 1515
///
///   @override
///   Type get debugTypicalAncestorWidgetClass => FrogJar;
1516 1517
/// }
/// ```
1518
/// {@end-tool}
1519 1520 1521 1522 1523 1524
///
/// See also:
///
///  * [RenderObject], the superclass for layout algorithms.
///  * [RenderObject.parentData], the slot that this class configures.
///  * [ParentData], the superclass of the data that will be placed in
1525 1526
///    [RenderObject.parentData] slots. The `T` type parameter for
///    [ParentDataWidget] is a [ParentData].
1527 1528 1529
///  * [RenderObjectWidget], the class for widgets that wrap [RenderObject]s.
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
1530
abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
1531 1532
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
Hixie's avatar
Hixie committed
1533
  const ParentDataWidget({ Key key, Widget child })
1534 1535
    : super(key: key, child: child);

1536
  @override
1537
  ParentDataElement<T> createElement() => ParentDataElement<T>(this);
1538

1539 1540
  /// Checks if this widget can apply its parent data to the provided
  /// `renderObject`.
1541
  ///
1542 1543 1544 1545 1546 1547 1548
  /// The [RenderObject.parentData] of the provided `renderObject` is
  /// typically set up by an ancestor [RenderObjectWidget] of the type returned
  /// by [debugTypicalAncestorWidgetClass].
  ///
  /// This is called just before [applyParentData] is invoked with the same
  /// [RenderObject] provided to that method.
  bool debugIsValidRenderObject(RenderObject renderObject) {
1549
    assert(T != dynamic);
1550 1551
    assert(T != ParentData);
    return renderObject.parentData is T;
1552 1553
  }

1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565
  /// The [RenderObjectWidget] that is typically used to set up the [ParentData]
  /// that [applyParentData] will write to.
  ///
  /// This is only used in error messages to tell users what widget typically
  /// wraps this ParentDataWidget.
  Type get debugTypicalAncestorWidgetClass;

  Iterable<DiagnosticsNode> _debugDescribeIncorrectParentDataType({
    @required ParentData parentData,
    RenderObjectWidget parentDataCreator,
    DiagnosticsNode ownershipChain,
  }) sync* {
1566
    assert(T != dynamic);
1567 1568 1569 1570 1571
    assert(T != ParentData);
    assert(debugTypicalAncestorWidgetClass != null);

    final String description = 'The ParentDataWidget $this wants to apply ParentData of type $T to a RenderObject';
    if (parentData == null) {
1572
      yield ErrorDescription(
1573
        '$description, which has not been set up to receive any ParentData.'
1574
      );
1575
    } else {
1576
      yield ErrorDescription(
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
        '$description, which has been set up to accept ParentData of incompatible type ${parentData.runtimeType}.'
      );
    }
    yield ErrorHint(
      'Usually, this means that the $runtimeType widget has the wrong ancestor RenderObjectWidget. '
      'Typically, $runtimeType widgets are placed directly inside $debugTypicalAncestorWidgetClass widgets.'
    );
    if (parentDataCreator != null) {
      yield ErrorHint(
        'The offending $runtimeType is currently placed inside a ${parentDataCreator.runtimeType} widget.'
      );
    }
    if (ownershipChain != null) {
      yield ErrorDescription(
        'The ownership chain for the RenderObject that received the incompatible parent data was:\n  $ownershipChain'
1592
      );
1593 1594
    }
  }
1595

1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
  /// Write the data from this widget into the given render object's parent data.
  ///
  /// The framework calls this function whenever it detects that the
  /// [RenderObject] associated with the [child] has outdated
  /// [RenderObject.parentData]. For example, if the render object was recently
  /// inserted into the render tree, the render object's parent data might not
  /// match the data in this widget.
  ///
  /// Subclasses are expected to override this function to copy data from their
  /// fields into the [RenderObject.parentData] field of the given render
  /// object. The render object's parent is guaranteed to have been created by a
  /// widget of type `T`, which usually means that this function can assume that
  /// the render object's parent data object inherits from a particular class.
  ///
  /// If this function modifies data that can change the parent's layout or
  /// painting, this function is responsible for calling
  /// [RenderObject.markNeedsLayout] or [RenderObject.markNeedsPaint] on the
  /// parent, as appropriate.
1614
  @protected
1615
  void applyParentData(RenderObject renderObject);
1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628

  /// Whether the [ParentDataElement.applyWidgetOutOfTurn] method is allowed
  /// with this widget.
  ///
  /// This should only return true if this widget represents a [ParentData]
  /// configuration that will have no impact on the layout or paint phase.
  ///
  /// See also:
  ///
  ///  * [ParentDataElement.applyWidgetOutOfTurn], which verifies this in debug
  ///    mode.
  @protected
  bool debugCanApplyOutOfTurn() => false;
1629
}
1630

1631 1632 1633
/// Base class for widgets that efficiently propagate information down the tree.
///
/// To obtain the nearest instance of a particular type of inherited widget from
1634
/// a build context, use [BuildContext.dependOnInheritedWidgetOfExactType].
1635 1636 1637
///
/// Inherited widgets, when referenced in this way, will cause the consumer to
/// rebuild when the inherited widget itself changes state.
1638
///
1639 1640
/// {@youtube 560 315 https://www.youtube.com/watch?v=Zbm3hjPjQMk}
///
1641
/// {@tool snippet}
1642 1643 1644 1645 1646
///
/// The following is a skeleton of an inherited widget called `FrogColor`:
///
/// ```dart
/// class FrogColor extends InheritedWidget {
1647
///   const FrogColor({
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
///     Key key,
///     @required this.color,
///     @required Widget child,
///   }) : assert(color != null),
///        assert(child != null),
///        super(key: key, child: child);
///
///   final Color color;
///
///   static FrogColor of(BuildContext context) {
1658
///     return context.dependOnInheritedWidgetOfExactType<FrogColor>();
1659 1660 1661 1662 1663 1664
///   }
///
///   @override
///   bool updateShouldNotify(FrogColor old) => color != old.color;
/// }
/// ```
1665
/// {@end-tool}
1666 1667
///
/// The convention is to provide a static method `of` on the [InheritedWidget]
1668
/// which does the call to [BuildContext.dependOnInheritedWidgetOfExactType]. This
1669 1670
/// allows the class to define its own fallback logic in case there isn't
/// a widget in scope. In the example above, the value returned will be
1671 1672 1673 1674
/// null in that case, but it could also have defaulted to a value.
///
/// Sometimes, the `of` method returns the data rather than the inherited
/// widget; for example, in this case it could have returned a [Color] instead
1675
/// of the `FrogColor` widget.
1676 1677 1678 1679 1680
///
/// Occasionally, the inherited widget is an implementation detail of another
/// class, and is therefore private. The `of` method in that case is typically
/// put on the public class instead. For example, [Theme] is implemented as a
/// [StatelessWidget] that builds a private inherited widget; [Theme.of] looks
1681
/// for that inherited widget using [BuildContext.dependOnInheritedWidgetOfExactType]
1682 1683
/// and then returns the [ThemeData].
///
1684 1685
/// {@youtube 560 315 https://www.youtube.com/watch?v=1t-8rBCGBYw}
///
1686 1687 1688 1689 1690 1691 1692
/// See also:
///
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
///  * [StatelessWidget], for widgets that always build the same way given a
///    particular configuration and ambient state.
///  * [Widget], for an overview of widgets in general.
1693 1694 1695 1696 1697
///  * [InheritedNotifier], an inherited widget whose value can be a
///    [Listenable], and which will notify dependents whenever the value
///    sends notifications.
///  * [InheritedModel], an inherited widget that allows clients to subscribe
///    to changes for subparts of the value.
1698
abstract class InheritedWidget extends ProxyWidget {
1699 1700
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1701 1702
  const InheritedWidget({ Key key, Widget child })
    : super(key: key, child: child);
1703

1704
  @override
1705
  InheritedElement createElement() => InheritedElement(this);
Eric Seidel's avatar
Eric Seidel committed
1706

1707 1708 1709 1710
  /// Whether the framework should notify widgets that inherit from this widget.
  ///
  /// When this widget is rebuilt, sometimes we need to rebuild the widgets that
  /// inherit from this widget but sometimes we do not. For example, if the data
1711 1712
  /// held by this widget is the same as the data held by `oldWidget`, then we
  /// do not need to rebuild the widgets that inherited the data held by
1713 1714 1715 1716 1717 1718
  /// `oldWidget`.
  ///
  /// The framework distinguishes these cases by calling this function with the
  /// widget that previously occupied this location in the tree as an argument.
  /// The given widget is guaranteed to have the same [runtimeType] as this
  /// object.
1719
  @protected
1720
  bool updateShouldNotify(covariant InheritedWidget oldWidget);
1721
}
1722

1723 1724 1725 1726
/// RenderObjectWidgets provide the configuration for [RenderObjectElement]s,
/// which wrap [RenderObject]s, which provide the actual rendering of the
/// application.
abstract class RenderObjectWidget extends Widget {
1727 1728
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1729 1730
  const RenderObjectWidget({ Key key }) : super(key: key);

1731
  /// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
1732
  @override
1733 1734
  RenderObjectElement createElement();

1735 1736 1737
  /// Creates an instance of the [RenderObject] class that this
  /// [RenderObjectWidget] represents, using the configuration described by this
  /// [RenderObjectWidget].
1738 1739 1740 1741 1742 1743
  ///
  /// This method should not do anything with the children of the render object.
  /// That should instead be handled by the method that overrides
  /// [RenderObjectElement.mount] in the object rendered by this object's
  /// [createElement] method. See, for example,
  /// [SingleChildRenderObjectElement.mount].
1744
  @protected
1745
  RenderObject createRenderObject(BuildContext context);
1746

1747 1748 1749
  /// Copies the configuration described by this [RenderObjectWidget] to the
  /// given [RenderObject], which will be of the same type as returned by this
  /// object's [createRenderObject].
1750 1751 1752 1753 1754 1755
  ///
  /// This method should not do anything to update the children of the render
  /// object. That should instead be handled by the method that overrides
  /// [RenderObjectElement.update] in the object rendered by this object's
  /// [createElement] method. See, for example,
  /// [SingleChildRenderObjectElement.update].
1756
  @protected
1757
  void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
1758

1759 1760 1761
  /// A render object previously associated with this widget has been removed
  /// from the tree. The given [RenderObject] will be of the same type as
  /// returned by this object's [createRenderObject].
1762
  @protected
1763
  void didUnmountRenderObject(covariant RenderObject renderObject) { }
1764 1765 1766 1767 1768
}

/// A superclass for RenderObjectWidgets that configure RenderObject subclasses
/// that have no children.
abstract class LeafRenderObjectWidget extends RenderObjectWidget {
1769 1770
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1771 1772
  const LeafRenderObjectWidget({ Key key }) : super(key: key);

1773
  @override
1774
  LeafRenderObjectElement createElement() => LeafRenderObjectElement(this);
1775 1776
}

1777
/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1778 1779
/// that have a single child slot. (This superclass only provides the storage
/// for that child, it doesn't actually provide the updating logic.)
1780 1781 1782 1783 1784
///
/// Typically, the render object assigned to this widget will make use of
/// [RenderObjectWithChildMixin] to implement a single-child model. The mixin
/// exposes a [RenderObjectWithChildMixin.child] property that allows
/// retrieving the render object belonging to the [child] widget.
1785
abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
1786 1787
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1788
  const SingleChildRenderObjectWidget({ Key key, this.child }) : super(key: key);
1789

1790
  /// The widget below this widget in the tree.
1791 1792
  ///
  /// {@macro flutter.widgets.child}
1793 1794
  final Widget child;

1795
  @override
1796
  SingleChildRenderObjectElement createElement() => SingleChildRenderObjectElement(this);
1797 1798
}

1799
/// A superclass for [RenderObjectWidget]s that configure [RenderObject] subclasses
1800 1801 1802
/// that have a single list of children. (This superclass only provides the
/// storage for that child list, it doesn't actually provide the updating
/// logic.)
1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
///
/// This will return a [RenderObject] mixing in [ContainerRenderObjectMixin],
/// which provides the necessary functionality to visit the children of the
/// container render object (the render object belonging to the [children] widgets).
/// Typically, this is a [RenderBox] with [RenderBoxContainerDefaultsMixin].
///
/// See also:
///
///  * [Stack], which uses [MultiChildRenderObjectWidget].
///  * [RenderStack], for an example implementation of the associated render object.
1813
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
1814
  /// Initializes fields for subclasses.
1815 1816 1817
  ///
  /// The [children] argument must not be null and must not contain any null
  /// objects.
1818
  MultiChildRenderObjectWidget({ Key key, this.children = const <Widget>[] })
1819
    : assert(children != null),
1820 1821 1822
      assert(() {
        final int index = children.indexOf(null);
        if (index >= 0) {
1823 1824 1825
          throw FlutterError(
            "$runtimeType's children must not contain any null values, "
            'but a null value was found at index $index'
1826 1827 1828 1829
          );
        }
        return true;
      }()), // https://github.com/dart-lang/sdk/issues/29276
1830
      super(key: key);
1831

1832 1833
  /// The widgets below this widget in the tree.
  ///
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888
  /// If this list is going to be mutated, it is usually wise to put a [Key] on
  /// each of the child widgets, so that the framework can match old
  /// configurations to new configurations and maintain the underlying render
  /// objects.
  ///
  /// Also, a [Widget] in Flutter is immutable, so directly modifying the
  /// [children] such as `someMultiChildRenderObjectWidget.children.add(...)` or
  /// as the example code below will result in incorrect behaviors. Whenever the
  /// children list is modified, a new list object should be provided.
  ///
  /// ```dart
  /// class SomeWidgetState extends State<SomeWidget> {
  ///   List<Widget> _children;
  ///
  ///   void initState() {
  ///     _children = [];
  ///   }
  ///
  ///   void someHandler() {
  ///     setState(() {
  ///         _children.add(...);
  ///     });
  ///   }
  ///
  ///   Widget build(...) {
  ///     // Reusing `List<Widget> _children` here is problematic.
  ///     return Row(children: _children);
  ///   }
  /// }
  /// ```
  ///
  /// The following code corrects the problem mentioned above.
  ///
  /// ```dart
  /// class SomeWidgetState extends State<SomeWidget> {
  ///   List<Widget> _children;
  ///
  ///   void initState() {
  ///     _children = [];
  ///   }
  ///
  ///   void someHandler() {
  ///     setState(() {
  ///       // The key here allows Flutter to reuse the underlying render
  ///       // objects even if the children list is recreated.
  ///       _children.add(ChildWidget(key: ...));
  ///     });
  ///   }
  ///
  ///   Widget build(...) {
  ///     // Always create a new list of children as a Widget is immutable.
  ///     return Row(children: List.from(_children));
  ///   }
  /// }
  /// ```
1889 1890
  final List<Widget> children;

1891
  @override
1892
  MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
1893 1894
}

Hixie's avatar
Hixie committed
1895 1896 1897

// ELEMENTS

1898 1899
enum _ElementLifecycle {
  initial,
1900 1901
  active,
  inactive,
1902
  defunct,
1903 1904
}

1905
class _InactiveElements {
1906
  bool _locked = false;
1907
  final Set<Element> _elements = HashSet<Element>();
1908

1909
  void _unmount(Element element) {
1910
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
1911 1912 1913 1914 1915 1916
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle) {
        if (element.widget.key is GlobalKey)
          debugPrint('Discarding $element from inactive elements list.');
      }
      return true;
1917
    }());
1918 1919
    element.visitChildren((Element child) {
      assert(child._parent == element);
1920
      _unmount(child);
1921
    });
1922 1923
    element.unmount();
    assert(element._debugLifecycleState == _ElementLifecycle.defunct);
1924 1925
  }

1926
  void _unmountAll() {
1927 1928 1929
    _locked = true;
    final List<Element> elements = _elements.toList()..sort(Element._sort);
    _elements.clear();
1930
    try {
1931
      elements.reversed.forEach(_unmount);
1932
    } finally {
1933
      assert(_elements.isEmpty);
1934 1935
      _locked = false;
    }
1936 1937
  }

1938
  static void _deactivateRecursively(Element element) {
1939 1940 1941
    assert(element._debugLifecycleState == _ElementLifecycle.active);
    element.deactivate();
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
1942
    element.visitChildren(_deactivateRecursively);
1943 1944 1945 1946
    assert(() {
      element.debugDeactivated();
      return true;
    }());
1947 1948
  }

1949 1950 1951 1952
  void add(Element element) {
    assert(!_locked);
    assert(!_elements.contains(element));
    assert(element._parent == null);
1953
    if (element._active)
1954
      _deactivateRecursively(element);
1955 1956
    _elements.add(element);
  }
1957 1958 1959 1960 1961 1962 1963 1964

  void remove(Element element) {
    assert(!_locked);
    assert(_elements.contains(element));
    assert(element._parent == null);
    _elements.remove(element);
    assert(!element._active);
  }
1965 1966 1967 1968 1969 1970

  bool debugContains(Element element) {
    bool result;
    assert(() {
      result = _elements.contains(element);
      return true;
1971
    }());
1972 1973
    return result;
  }
1974 1975
}

1976 1977 1978 1979 1980 1981
/// Signature for the callback to [BuildContext.visitChildElements].
///
/// The argument is the child being visited.
///
/// It is safe to call `element.visitChildElements` reentrantly within
/// this callback.
1982
typedef ElementVisitor = void Function(Element element);
1983

1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020
/// A handle to the location of a widget in the widget tree.
///
/// This class presents a set of methods that can be used from
/// [StatelessWidget.build] methods and from methods on [State] objects.
///
/// [BuildContext] objects are passed to [WidgetBuilder] functions (such as
/// [StatelessWidget.build]), and are available from the [State.context] member.
/// Some static functions (e.g. [showDialog], [Theme.of], and so forth) also
/// take build contexts so that they can act on behalf of the calling widget, or
/// obtain data specifically for the given context.
///
/// Each widget has its own [BuildContext], which becomes the parent of the
/// widget returned by the [StatelessWidget.build] or [State.build] function.
/// (And similarly, the parent of any children for [RenderObjectWidget]s.)
///
/// In particular, this means that within a build method, the build context of
/// the widget of the build method is not the same as the build context of the
/// widgets returned by that build method. This can lead to some tricky cases.
/// For example, [Theme.of(context)] looks for the nearest enclosing [Theme] of
/// the given build context. If a build method for a widget Q includes a [Theme]
/// within its returned widget tree, and attempts to use [Theme.of] passing its
/// own context, the build method for Q will not find that [Theme] object. It
/// will instead find whatever [Theme] was an ancestor to the widget Q. If the
/// build context for a subpart of the returned tree is needed, a [Builder]
/// widget can be used: the build context passed to the [Builder.builder]
/// callback will be that of the [Builder] itself.
///
/// For example, in the following snippet, the [ScaffoldState.showSnackBar]
/// method is called on the [Scaffold] widget that the build method itself
/// creates. If a [Builder] had not been used, and instead the `context`
/// argument of the build method itself had been used, no [Scaffold] would have
/// been found, and the [Scaffold.of] function would have returned null.
///
/// ```dart
///   @override
///   Widget build(BuildContext context) {
///     // here, Scaffold.of(context) returns null
2021 2022 2023
///     return Scaffold(
///       appBar: AppBar(title: Text('Demo')),
///       body: Builder(
2024
///         builder: (BuildContext context) {
2025 2026
///           return FlatButton(
///             child: Text('BUTTON'),
2027 2028
///             onPressed: () {
///               // here, Scaffold.of(context) returns the locally created Scaffold
2029 2030
///               Scaffold.of(context).showSnackBar(SnackBar(
///                 content: Text('Hello.')
2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
///               ));
///             }
///           );
///         }
///       )
///     );
///   }
/// ```
///
/// The [BuildContext] for a particular widget can change location over time as
/// the widget is moved around the tree. Because of this, values returned from
/// the methods on this class should not be cached beyond the execution of a
/// single synchronous function.
///
/// [BuildContext] objects are actually [Element] objects. The [BuildContext]
/// interface is used to discourage direct manipulation of [Element] objects.
2047
abstract class BuildContext {
2048
  /// The current configuration of the [Element] that is this [BuildContext].
2049
  Widget get widget;
2050

2051 2052 2053 2054
  /// The [BuildOwner] for this context. The [BuildOwner] is in charge of
  /// managing the rendering pipeline for this context.
  BuildOwner get owner;

2055 2056
  /// Whether the [widget] is currently updating the widget or render tree.
  ///
2057
  /// For [StatefulWidget]s and [StatelessWidget]s this flag is true while
2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070
  /// their respective build methods are executing.
  /// [RenderObjectWidget]s set this to true while creating or configuring their
  /// associated [RenderObject]s.
  /// Other [Widget] types may set this to true for conceptually similar phases
  /// of their lifecycle.
  ///
  /// When this is true, it is safe for [widget] to establish a dependency to an
  /// [InheritedWidget] by calling [dependOnInheritedElement] or
  /// [dependOnInheritedWidgetOfExactType].
  ///
  /// Accessing this flag in release mode is not valid.
  bool get debugDoingBuild;

2071 2072 2073 2074 2075 2076
  /// The current [RenderObject] for the widget. If the widget is a
  /// [RenderObjectWidget], this is the render object that the widget created
  /// for itself. Otherwise, it is the render object of the first descendant
  /// [RenderObjectWidget].
  ///
  /// This method will only return a valid result after the build phase is
2077 2078
  /// complete. It is therefore not valid to call this from a build method.
  /// It should only be called from interaction event handlers (e.g.
2079 2080 2081
  /// gesture callbacks) or layout or paint callbacks.
  ///
  /// If the render object is a [RenderBox], which is the common case, then the
2082 2083 2084 2085
  /// size of the render object can be obtained from the [size] getter. This is
  /// only valid after the layout phase, and should therefore only be examined
  /// from paint callbacks or interaction event handlers (e.g. gesture
  /// callbacks).
2086
  ///
2087 2088
  /// For details on the different phases of a frame, see the discussion at
  /// [WidgetsBinding.drawFrame].
2089 2090 2091 2092 2093
  ///
  /// Calling this method is theoretically relatively expensive (O(N) in the
  /// depth of the tree), but in practice is usually cheap because the tree
  /// usually has many render objects and therefore the distance to the nearest
  /// render object is usually short.
2094
  RenderObject findRenderObject();
2095

2096 2097 2098
  /// The size of the [RenderBox] returned by [findRenderObject].
  ///
  /// This getter will only return a valid result after the layout phase is
2099 2100
  /// complete. It is therefore not valid to call this from a build method.
  /// It should only be called from paint callbacks or interaction event
2101 2102
  /// handlers (e.g. gesture callbacks).
  ///
2103 2104
  /// For details on the different phases of a frame, see the discussion at
  /// [WidgetsBinding.drawFrame].
2105 2106 2107
  ///
  /// This getter will only return a valid result if [findRenderObject] actually
  /// returns a [RenderBox]. If [findRenderObject] returns a render object that
2108
  /// is not a subtype of [RenderBox] (e.g., [RenderView]), this getter will
2109 2110 2111 2112 2113 2114 2115 2116
  /// throw an exception in checked mode and will return null in release mode.
  ///
  /// Calling this getter is theoretically relatively expensive (O(N) in the
  /// depth of the tree), but in practice is usually cheap because the tree
  /// usually has many render objects and therefore the distance to the nearest
  /// render object is usually short.
  Size get size;

2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
  /// Registers this build context with [ancestor] such that when
  /// [ancestor]'s widget changes this build context is rebuilt.
  ///
  /// This method is deprecated. Please use [dependOnInheritedElement] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use dependOnInheritedElement instead. '
    'This feature was deprecated after v1.12.1.'
  )
  InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect });

2128 2129 2130 2131 2132 2133
  /// Registers this build context with [ancestor] such that when
  /// [ancestor]'s widget changes this build context is rebuilt.
  ///
  /// Returns `ancestor.widget`.
  ///
  /// This method is rarely called directly. Most applications should use
2134
  /// [dependOnInheritedWidgetOfExactType], which calls this method after finding
2135 2136
  /// the appropriate [InheritedElement] ancestor.
  ///
2137
  /// All of the qualifications about when [dependOnInheritedWidgetOfExactType] can
2138
  /// be called apply to this method as well.
2139
  InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
2140

2141 2142 2143 2144 2145 2146
  /// Obtains the nearest widget of the given type, which must be the type of a
  /// concrete [InheritedWidget] subclass, and registers this build context with
  /// that widget such that when that widget changes (or a new widget of that
  /// type is introduced, or the widget goes away), this build context is
  /// rebuilt so that it can obtain new values from that widget.
  ///
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160
  /// This method is deprecated. Please use [dependOnInheritedWidgetOfExactType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use dependOnInheritedWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  InheritedWidget inheritFromWidgetOfExactType(Type targetType, { Object aspect });

  /// Obtains the nearest widget of the given type [T], which must be the type of a
  /// concrete [InheritedWidget] subclass, and registers this build context with
  /// that widget such that when that widget changes (or a new widget of that
  /// type is introduced, or the widget goes away), this build context is
  /// rebuilt so that it can obtain new values from that widget.
  ///
2161 2162 2163
  /// This is typically called implicitly from `of()` static methods, e.g.
  /// [Theme.of].
  ///
2164
  /// This method should not be called from widget constructors or from
2165 2166 2167
  /// [State.initState] methods, because those methods would not get called
  /// again if the inherited value were to change. To ensure that the widget
  /// correctly updates itself when the inherited value changes, only call this
2168
  /// (directly or indirectly) from build methods, layout and paint callbacks, or
2169
  /// from [State.didChangeDependencies].
2170
  ///
2171 2172 2173 2174 2175
  /// This method should not be called from [State.dispose] because the element
  /// tree is no longer stable at that time. To refer to an ancestor from that
  /// method, save a reference to the ancestor in [State.didChangeDependencies].
  /// It is safe to use this method from [State.deactivate], which is called
  /// whenever the widget is removed from the tree.
2176
  ///
2177 2178 2179
  /// It is also possible to call this method from interaction event handlers
  /// (e.g. gesture callbacks) or timers, to obtain a value once, if that value
  /// is not going to be cached and reused later.
2180 2181 2182
  ///
  /// Calling this method is O(1) with a small constant factor, but will lead to
  /// the widget being rebuilt more often.
2183 2184
  ///
  /// Once a widget registers a dependency on a particular type by calling this
2185
  /// method, it will be rebuilt, and [State.didChangeDependencies] will be
2186 2187 2188
  /// called, whenever changes occur relating to that widget until the next time
  /// the widget or one of its ancestors is moved (for example, because an
  /// ancestor is added or removed).
2189
  ///
2190
  /// The [aspect] parameter is only used when [T] is an
2191 2192 2193
  /// [InheritedWidget] subclasses that supports partial updates, like
  /// [InheritedModel]. It specifies what "aspect" of the inherited
  /// widget this context depends on.
2194
  T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object aspect });
2195

Matt Perry's avatar
Matt Perry committed
2196 2197 2198
  /// Obtains the element corresponding to the nearest widget of the given type,
  /// which must be the type of a concrete [InheritedWidget] subclass.
  ///
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
  /// This method is deprecated. Please use [getElementForInheritedWidgetOfExactType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use getElementForInheritedWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  InheritedElement ancestorInheritedElementForWidgetOfExactType(Type targetType);

  /// Obtains the element corresponding to the nearest widget of the given type [T],
  /// which must be the type of a concrete [InheritedWidget] subclass.
  ///
2210 2211
  /// Returns null if no such element is found.
  ///
Matt Perry's avatar
Matt Perry committed
2212 2213 2214
  /// Calling this method is O(1) with a small constant factor.
  ///
  /// This method does not establish a relationship with the target in the way
2215
  /// that [dependOnInheritedWidgetOfExactType] does.
2216
  ///
2217 2218 2219
  /// This method should not be called from [State.dispose] because the element
  /// tree is no longer stable at that time. To refer to an ancestor from that
  /// method, save a reference to the ancestor by calling
2220
  /// [dependOnInheritedWidgetOfExactType] in [State.didChangeDependencies]. It is
2221 2222
  /// safe to use this method from [State.deactivate], which is called whenever
  /// the widget is removed from the tree.
2223
  InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
Matt Perry's avatar
Matt Perry committed
2224

2225 2226 2227
  /// Returns the nearest ancestor widget of the given type, which must be the
  /// type of a concrete [Widget] subclass.
  ///
2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
  /// This method is deprecated. Please use [findAncestorWidgetOfExactType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  Widget ancestorWidgetOfExactType(Type targetType);

  /// Returns the nearest ancestor widget of the given type [T], which must be the
  /// type of a concrete [Widget] subclass.
  ///
2239 2240 2241 2242 2243 2244 2245 2246 2247
  /// In general, [dependOnInheritedWidgetOfExactType] is more useful, since
  /// inherited widgets will trigger consumers to rebuild when they change. This
  /// method is appropriate when used in interaction event handlers (e.g.
  /// gesture callbacks) or for performing one-off tasks such as asserting that
  /// you have or don't have a widget of a specific type as an ancestor. The
  /// return value of a Widget's build method should not depend on the value
  /// returned by this method, because the build context will not rebuild if the
  /// return value of this method changes. This could lead to a situation where
  /// data used in the build method changes, but the widget is not rebuilt.
2248 2249 2250 2251
  ///
  /// Calling this method is relatively expensive (O(N) in the depth of the
  /// tree). Only call this method if the distance from this widget to the
  /// desired ancestor is known to be small and bounded.
2252 2253 2254 2255
  ///
  /// This method should not be called from [State.deactivate] or [State.dispose]
  /// because the widget tree is no longer stable at that time. To refer to
  /// an ancestor from one of those methods, save a reference to the ancestor
2256
  /// by calling [findAncestorWidgetOfExactType] in [State.didChangeDependencies].
2257 2258 2259
  ///
  /// Returns null if a widget of the requested type does not appear in the
  /// ancestors of this context.
2260
  T findAncestorWidgetOfExactType<T extends Widget>();
2261 2262 2263 2264

  /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
  /// that matches the given [TypeMatcher].
  ///
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275
  /// This method is deprecated. Please use [findAncestorStateOfType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorStateOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  State ancestorStateOfType(TypeMatcher matcher);

  /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
  /// that is an instance of the given type [T].
  ///
2276 2277
  /// This should not be used from build methods, because the build context will
  /// not be rebuilt if the value that would be returned by this method changes.
2278
  /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2279
  /// cases. This method is useful for changing the state of an ancestor widget in
2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291
  /// a one-off manner, for example, to cause an ancestor scrolling list to
  /// scroll this build context's widget into view, or to move the focus in
  /// response to user interaction.
  ///
  /// In general, though, consider using a callback that triggers a stateful
  /// change in the ancestor rather than using the imperative style implied by
  /// this method. This will usually lead to more maintainable and reusable code
  /// since it decouples widgets from each other.
  ///
  /// Calling this method is relatively expensive (O(N) in the depth of the
  /// tree). Only call this method if the distance from this widget to the
  /// desired ancestor is known to be small and bounded.
2292
  ///
2293 2294 2295
  /// This method should not be called from [State.deactivate] or [State.dispose]
  /// because the widget tree is no longer stable at that time. To refer to
  /// an ancestor from one of those methods, save a reference to the ancestor
2296
  /// by calling [findAncestorStateOfType] in [State.didChangeDependencies].
2297
  ///
2298
  /// {@tool snippet}
2299 2300
  ///
  /// ```dart
2301
  /// ScrollableState scrollable = context.findAncestorStateOfType<ScrollableState>();
2302
  /// ```
2303
  /// {@end-tool}
2304
  T findAncestorStateOfType<T extends State>();
2305

2306 2307 2308
  /// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
  /// that matches the given [TypeMatcher].
  ///
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321
  /// This method is deprecated. Please use [findRootAncestorStateOfType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findRootAncestorStateOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  State rootAncestorStateOfType(TypeMatcher matcher);

  /// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
  /// that is an instance of the given type [T].
  ///
  /// Functions the same way as [findAncestorStateOfType] but keeps visiting subsequent
  /// ancestors until there are none of the type instance of [T] remaining.
2322 2323 2324 2325
  /// Then returns the last one found.
  ///
  /// This operation is O(N) as well though N is the entire widget tree rather than
  /// a subtree.
2326
  T findRootAncestorStateOfType<T extends State>();
2327

2328 2329 2330
  /// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
  /// that matches the given [TypeMatcher].
  ///
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
  /// This method is deprecated. Please use [findAncestorRenderObjectOfType] instead.
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorRenderObjectOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
  RenderObject ancestorRenderObjectOfType(TypeMatcher matcher);

  /// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
  /// that is an instance of the given type [T].
  ///
2342 2343
  /// This should not be used from build methods, because the build context will
  /// not be rebuilt if the value that would be returned by this method changes.
2344
  /// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
2345 2346 2347 2348 2349 2350 2351 2352
  /// cases. This method is useful only in esoteric cases where a widget needs
  /// to cause an ancestor to change its layout or paint behavior. For example,
  /// it is used by [Material] so that [InkWell] widgets can trigger the ink
  /// splash on the [Material]'s actual render object.
  ///
  /// Calling this method is relatively expensive (O(N) in the depth of the
  /// tree). Only call this method if the distance from this widget to the
  /// desired ancestor is known to be small and bounded.
2353 2354 2355 2356
  ///
  /// This method should not be called from [State.deactivate] or [State.dispose]
  /// because the widget tree is no longer stable at that time. To refer to
  /// an ancestor from one of those methods, save a reference to the ancestor
2357 2358
  /// by calling [findAncestorRenderObjectOfType] in [State.didChangeDependencies].
  T findAncestorRenderObjectOfType<T extends RenderObject>();
2359 2360 2361 2362 2363 2364 2365 2366 2367 2368

  /// Walks the ancestor chain, starting with the parent of this build context's
  /// widget, invoking the argument for each ancestor. The callback is given a
  /// reference to the ancestor widget's corresponding [Element] object. The
  /// walk stops when it reaches the root widget or when the callback returns
  /// false. The callback must not return null.
  ///
  /// This is useful for inspecting the widget tree.
  ///
  /// Calling this method is relatively expensive (O(N) in the depth of the tree).
2369 2370 2371 2372
  ///
  /// This method should not be called from [State.deactivate] or [State.dispose]
  /// because the element tree is no longer stable at that time. To refer to
  /// an ancestor from one of those methods, save a reference to the ancestor
2373
  /// by calling [visitAncestorElements] in [State.didChangeDependencies].
2374
  void visitAncestorElements(bool visitor(Element element));
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394

  /// Walks the children of this widget.
  ///
  /// This is useful for applying changes to children after they are built
  /// without waiting for the next frame, especially if the children are known,
  /// and especially if there is exactly one child (as is always the case for
  /// [StatefulWidget]s or [StatelessWidget]s).
  ///
  /// Calling this method is very cheap for build contexts that correspond to
  /// [StatefulWidget]s or [StatelessWidget]s (O(1), since there's only one
  /// child).
  ///
  /// Calling this method is potentially expensive for build contexts that
  /// correspond to [RenderObjectWidget]s (O(N) in the number of children).
  ///
  /// Calling this method recursively is extremely expensive (O(N) in the number
  /// of descendants), and should be avoided if possible. Generally it is
  /// significantly cheaper to use an [InheritedWidget] and have the descendants
  /// pull data down, than it is to use [visitChildElements] recursively to push
  /// data down to them.
2395
  void visitChildElements(ElementVisitor visitor);
2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413

  /// Returns a description of an [Element] from the current build context.
  DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});

  /// Returns a description of the [Widget] associated with the current build context.
  DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty});

  /// Adds a description of a specific type of widget missing from the current
  /// build context's ancestry tree.
  ///
  /// You can find an example of using this method in [debugCheckHasMaterial].
  List<DiagnosticsNode> describeMissingAncestor({ @required Type expectedAncestorType });

  /// Adds a description of the ownership chain from a specific [Element]
  /// to the error report.
  ///
  /// The ownership chain is useful for debugging the source of an element.
  DiagnosticsNode describeOwnershipChain(String name);
2414
}
2415

2416 2417 2418 2419 2420
/// Manager class for the widgets framework.
///
/// This class tracks which widgets need rebuilding, and handles other tasks
/// that apply to widget trees as a whole, such as managing the inactive element
/// list for the tree and triggering the "reassemble" command when necessary
2421
/// during hot reload when debugging.
2422 2423 2424 2425 2426 2427 2428 2429 2430 2431
///
/// The main build owner is typically owned by the [WidgetsBinding], and is
/// driven from the operating system along with the rest of the
/// build/layout/paint pipeline.
///
/// Additional build owners can be built to manage off-screen widget trees.
///
/// To assign a build owner to a tree, use the
/// [RootRenderObjectElement.assignOwner] method on the root element of the
/// widget tree.
2432
class BuildOwner {
2433
  /// Creates an object that manages widgets.
2434 2435
  BuildOwner({ this.onBuildScheduled });

2436 2437
  /// Called on each build pass when the first buildable element is marked
  /// dirty.
2438 2439
  VoidCallback onBuildScheduled;

2440
  final _InactiveElements _inactiveElements = _InactiveElements();
2441

2442
  final List<Element> _dirtyElements = <Element>[];
2443
  bool _scheduledFlushDirtyElements = false;
2444 2445 2446

  /// Whether [_dirtyElements] need to be sorted again as a result of more
  /// elements becoming dirty during the build.
2447
  ///
2448
  /// This is necessary to preserve the sort order defined by [Element._sort].
2449
  ///
2450 2451 2452 2453 2454
  /// This field is set to null when [buildScope] is not actively rebuilding
  /// the widget tree.
  bool _dirtyElementsNeedsResorting;

  /// Whether [buildScope] is actively rebuilding the widget tree.
2455
  ///
2456 2457
  /// [scheduleBuildFor] should only be called when this value is true.
  bool get _debugIsInBuildScope => _dirtyElementsNeedsResorting != null;
2458

2459 2460 2461 2462 2463 2464
  /// The object in charge of the focus tree.
  ///
  /// Rarely used directly. Instead, consider using [FocusScope.of] to obtain
  /// the [FocusScopeNode] for a given [BuildContext].
  ///
  /// See [FocusManager] for more details.
2465
  FocusManager focusManager = FocusManager();
2466

2467
  /// Adds an element to the dirty elements list so that it will be rebuilt
2468
  /// when [WidgetsBinding.drawFrame] calls [buildScope].
2469
  void scheduleBuildFor(Element element) {
2470 2471
    assert(element != null);
    assert(element.owner == this);
2472
    assert(() {
2473 2474
      if (debugPrintScheduleBuildForStacks)
        debugPrintStack(label: 'scheduleBuildFor() called for $element${_dirtyElements.contains(element) ? " (ALREADY IN LIST)" : ""}');
2475
      if (!element.dirty) {
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('scheduleBuildFor() called for a widget that is not marked as dirty.'),
          element.describeElement('The method was called for the following element'),
          ErrorDescription(
            'This element is not current marked as dirty. Make sure to set the dirty flag before '
            'calling scheduleBuildFor().'),
          ErrorHint(
            'If you did not attempt to call scheduleBuildFor() yourself, then this probably '
            'indicates a bug in the widgets framework. Please report it:\n'
            '  https://github.com/flutter/flutter/issues/new?template=BUG.md'
2486
          ),
2487
        ]);
2488 2489
      }
      return true;
2490
    }());
2491 2492 2493
    if (element._inDirtyList) {
      assert(() {
        if (debugPrintScheduleBuildForStacks)
2494 2495
          debugPrintStack(label: 'BuildOwner.scheduleBuildFor() called; _dirtyElementsNeedsResorting was $_dirtyElementsNeedsResorting (now true); dirty list is: $_dirtyElements');
        if (!_debugIsInBuildScope) {
2496 2497 2498 2499 2500
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('BuildOwner.scheduleBuildFor() called inappropriately.'),
            ErrorHint(
              'The BuildOwner.scheduleBuildFor() method should only be called while the '
              'buildScope() method is actively rebuilding the widget tree.'
2501
            ),
2502
          ]);
2503 2504
        }
        return true;
2505
      }());
2506 2507 2508
      _dirtyElementsNeedsResorting = true;
      return;
    }
2509 2510
    if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      _scheduledFlushDirtyElements = true;
2511
      onBuildScheduled();
2512
    }
2513
    _dirtyElements.add(element);
2514
    element._inDirtyList = true;
2515 2516 2517 2518
    assert(() {
      if (debugPrintScheduleBuildForStacks)
        debugPrint('...dirty list is now: $_dirtyElements');
      return true;
2519
    }());
2520 2521 2522 2523
  }

  int _debugStateLockLevel = 0;
  bool get _debugStateLocked => _debugStateLockLevel > 0;
2524 2525 2526 2527 2528

  /// Whether this widget tree is in the build phase.
  ///
  /// Only valid when asserts are enabled.
  bool get debugBuilding => _debugBuilding;
2529
  bool _debugBuilding = false;
2530
  Element _debugCurrentBuildTarget;
2531

2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542
  /// Establishes a scope in which calls to [State.setState] are forbidden, and
  /// calls the given `callback`.
  ///
  /// This mechanism is used to ensure that, for instance, [State.dispose] does
  /// not call [State.setState].
  void lockState(void callback()) {
    assert(callback != null);
    assert(_debugStateLockLevel >= 0);
    assert(() {
      _debugStateLockLevel += 1;
      return true;
2543
    }());
2544 2545 2546 2547 2548 2549
    try {
      callback();
    } finally {
      assert(() {
        _debugStateLockLevel -= 1;
        return true;
2550
      }());
2551 2552 2553 2554 2555 2556 2557
    }
    assert(_debugStateLockLevel >= 0);
  }

  /// Establishes a scope for updating the widget tree, and calls the given
  /// `callback`, if any. Then, builds all the elements that were marked as
  /// dirty using [scheduleBuildFor], in depth order.
2558
  ///
2559 2560
  /// This mechanism prevents build methods from transitively requiring other
  /// build methods to run, potentially causing infinite loops.
2561
  ///
2562 2563 2564 2565 2566 2567 2568 2569
  /// The dirty list is processed after `callback` returns, building all the
  /// elements that were marked as dirty using [scheduleBuildFor], in depth
  /// order. If elements are marked as dirty while this method is running, they
  /// must be deeper than the `context` node, and deeper than any
  /// previously-built node in this pass.
  ///
  /// To flush the current dirty list without performing any other work, this
  /// function can be called with no callback. This is what the framework does
2570
  /// each frame, in [WidgetsBinding.drawFrame].
2571 2572
  ///
  /// Only one [buildScope] can be active at a time.
2573
  ///
2574
  /// A [buildScope] implies a [lockState] scope as well.
2575 2576 2577 2578 2579
  ///
  /// To print a console message every time this method is called, set
  /// [debugPrintBuildScope] to true. This is useful when debugging problems
  /// involving widgets not getting marked dirty, or getting marked dirty too
  /// often.
2580
  void buildScope(Element context, [ VoidCallback callback ]) {
2581 2582 2583
    if (callback == null && _dirtyElements.isEmpty)
      return;
    assert(context != null);
2584
    assert(_debugStateLockLevel >= 0);
2585
    assert(!_debugBuilding);
2586
    assert(() {
2587 2588
      if (debugPrintBuildScope)
        debugPrint('buildScope called with context $context; dirty list is: $_dirtyElements');
2589
      _debugStateLockLevel += 1;
2590
      _debugBuilding = true;
2591
      return true;
2592
    }());
2593
    Timeline.startSync('Build', arguments: timelineWhitelistArguments);
2594
    try {
2595
      _scheduledFlushDirtyElements = true;
2596 2597
      if (callback != null) {
        assert(_debugStateLocked);
2598
        Element debugPreviousBuildTarget;
2599 2600 2601 2602
        assert(() {
          context._debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
          debugPreviousBuildTarget = _debugCurrentBuildTarget;
          _debugCurrentBuildTarget = context;
2603
          return true;
2604
        }());
2605
        _dirtyElementsNeedsResorting = false;
2606 2607 2608 2609 2610 2611 2612
        try {
          callback();
        } finally {
          assert(() {
            context._debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
            assert(_debugCurrentBuildTarget == context);
            _debugCurrentBuildTarget = debugPreviousBuildTarget;
2613
            _debugElementWasRebuilt(context);
2614
            return true;
2615
          }());
2616 2617
        }
      }
2618
      _dirtyElements.sort(Element._sort);
2619
      _dirtyElementsNeedsResorting = false;
2620 2621 2622 2623 2624 2625
      int dirtyCount = _dirtyElements.length;
      int index = 0;
      while (index < dirtyCount) {
        assert(_dirtyElements[index] != null);
        assert(_dirtyElements[index]._inDirtyList);
        assert(!_dirtyElements[index]._active || _dirtyElements[index]._debugIsInScope(context));
Ian Hickson's avatar
Ian Hickson committed
2626 2627 2628 2629
        try {
          _dirtyElements[index].rebuild();
        } catch (e, stack) {
          _debugReportException(
2630 2631 2632 2633
            ErrorDescription('while rebuilding dirty elements'),
            e,
            stack,
            informationCollector: () sync* {
2634
              yield DiagnosticsDebugCreator(DebugCreator(_dirtyElements[index]));
2635
              yield _dirtyElements[index].describeElement('The element being rebuilt at the time was index $index of $dirtyCount');
2636
            },
Ian Hickson's avatar
Ian Hickson committed
2637 2638
          );
        }
2639
        index += 1;
2640
        if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting) {
2641
          _dirtyElements.sort(Element._sort);
2642
          _dirtyElementsNeedsResorting = false;
2643
          dirtyCount = _dirtyElements.length;
2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
          while (index > 0 && _dirtyElements[index - 1].dirty) {
            // It is possible for previously dirty but inactive widgets to move right in the list.
            // We therefore have to move the index left in the list to account for this.
            // We don't know how many could have moved. However, we do know that the only possible
            // change to the list is that nodes that were previously to the left of the index have
            // now moved to be to the right of the right-most cleaned node, and we do know that
            // all the clean nodes were to the left of the index. So we move the index left
            // until just after the right-most clean node.
            index -= 1;
          }
2654 2655
        }
      }
2656
      assert(() {
2657
        if (_dirtyElements.any((Element element) => element._active && element.dirty)) {
2658 2659 2660
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('buildScope missed some dirty elements.'),
            ErrorHint('This probably indicates that the dirty list should have been resorted but was not.'),
2661
            Element.describeElements('The list of dirty elements at the end of the buildScope call was', _dirtyElements),
2662
          ]);
2663 2664
        }
        return true;
2665
      }());
Ian Hickson's avatar
Ian Hickson committed
2666
    } finally {
2667
      for (final Element element in _dirtyElements) {
2668 2669 2670 2671 2672
        assert(element._inDirtyList);
        element._inDirtyList = false;
      }
      _dirtyElements.clear();
      _scheduledFlushDirtyElements = false;
2673
      _dirtyElementsNeedsResorting = null;
2674 2675
      Timeline.finishSync();
      assert(_debugBuilding);
2676
      assert(() {
2677
        _debugBuilding = false;
2678
        _debugStateLockLevel -= 1;
2679 2680
        if (debugPrintBuildScope)
          debugPrint('buildScope finished');
2681
        return true;
2682
      }());
2683 2684 2685 2686
    }
    assert(_debugStateLockLevel >= 0);
  }

2687 2688 2689
  Map<Element, Set<GlobalKey>> _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans;

  void _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(Element node, GlobalKey key) {
2690
    _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans ??= HashMap<Element, Set<GlobalKey>>();
2691
    final Set<GlobalKey> keys = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans
2692
      .putIfAbsent(node, () => HashSet<GlobalKey>());
2693 2694 2695 2696 2697 2698 2699
    keys.add(key);
  }

  void _debugElementWasRebuilt(Element node) {
    _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.remove(node);
  }

2700 2701
  /// Complete the element build pass by unmounting any elements that are no
  /// longer active.
2702
  ///
2703
  /// This is called by [WidgetsBinding.drawFrame].
2704
  ///
2705 2706
  /// In debug mode, this also runs some sanity checks, for example checking for
  /// duplicate global keys.
2707 2708 2709
  ///
  /// After the current call stack unwinds, a microtask that notifies listeners
  /// about changes to global keys will run.
2710
  void finalizeTree() {
2711
    Timeline.startSync('Finalize tree', arguments: timelineWhitelistArguments);
2712 2713
    try {
      lockState(() {
2714 2715 2716 2717
        _inactiveElements._unmountAll(); // this unregisters the GlobalKeys
      });
      assert(() {
        try {
2718
          GlobalKey._debugVerifyGlobalKeyReservation();
2719 2720 2721
          GlobalKey._debugVerifyIllFatedPopulation();
          if (_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans != null &&
              _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.isNotEmpty) {
2722
            final Set<GlobalKey> keys = HashSet<GlobalKey>();
2723
            for (final Element element in _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.keys) {
2724 2725 2726 2727
              if (element._debugLifecycleState != _ElementLifecycle.defunct)
                keys.addAll(_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans[element]);
            }
            if (keys.isNotEmpty) {
2728
              final Map<String, int> keyStringCount = HashMap<String, int>();
2729
              for (final String key in keys.map<String>((GlobalKey key) => key.toString())) {
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744
                if (keyStringCount.containsKey(key)) {
                  keyStringCount[key] += 1;
                } else {
                  keyStringCount[key] = 1;
                }
              }
              final List<String> keyLabels = <String>[];
              keyStringCount.forEach((String key, int count) {
                if (count == 1) {
                  keyLabels.add(key);
                } else {
                  keyLabels.add('$key ($count different affected keys had this toString representation)');
                }
              });
              final Iterable<Element> elements = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.keys;
2745
              final Map<String, int> elementStringCount = HashMap<String, int>();
2746
              for (final String element in elements.map<String>((Element element) => element.toString())) {
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772
                if (elementStringCount.containsKey(element)) {
                  elementStringCount[element] += 1;
                } else {
                  elementStringCount[element] = 1;
                }
              }
              final List<String> elementLabels = <String>[];
              elementStringCount.forEach((String element, int count) {
                if (count == 1) {
                  elementLabels.add(element);
                } else {
                  elementLabels.add('$element ($count different affected elements had this toString representation)');
                }
              });
              assert(keyLabels.isNotEmpty);
              final String the = keys.length == 1 ? ' the' : '';
              final String s = keys.length == 1 ? '' : 's';
              final String were = keys.length == 1 ? 'was' : 'were';
              final String their = keys.length == 1 ? 'its' : 'their';
              final String respective = elementLabels.length == 1 ? '' : ' respective';
              final String those = keys.length == 1 ? 'that' : 'those';
              final String s2 = elementLabels.length == 1 ? '' : 's';
              final String those2 = elementLabels.length == 1 ? 'that' : 'those';
              final String they = elementLabels.length == 1 ? 'it' : 'they';
              final String think = elementLabels.length == 1 ? 'thinks' : 'think';
              final String are = elementLabels.length == 1 ? 'is' : 'are';
2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790
              // TODO(jacobr): make this error more structured to better expose which widgets had problems.
              throw FlutterError.fromParts(<DiagnosticsNode>[
                ErrorSummary('Duplicate GlobalKey$s detected in widget tree.'),
                // TODO(jacobr): refactor this code so the elements are clickable
                // in GUI debug tools.
                ErrorDescription(
                  'The following GlobalKey$s $were specified multiple times in the widget tree. This will lead to '
                  'parts of the widget tree being truncated unexpectedly, because the second time a key is seen, '
                  'the previous instance is moved to the new location. The key$s $were:\n'
                  '- ${keyLabels.join("\n  ")}\n'
                  'This was determined by noticing that after$the widget$s with the above global key$s $were moved '
                  'out of $their$respective previous parent$s2, $those2 previous parent$s2 never updated during this frame, meaning '
                  'that $they either did not update at all or updated before the widget$s $were moved, in either case '
                  'implying that $they still $think that $they should have a child with $those global key$s.\n'
                  'The specific parent$s2 that did not update after having one or more children forcibly removed '
                  'due to GlobalKey reparenting $are:\n'
                  '- ${elementLabels.join("\n  ")}'
                  '\nA GlobalKey can only be specified on one widget at a time in the widget tree.'
2791
                ),
2792
              ]);
2793 2794 2795 2796 2797 2798
            }
          }
        } finally {
          _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.clear();
        }
        return true;
2799
      }());
2800
    } catch (e, stack) {
2801 2802 2803
      // Catching the exception directly to avoid activating the ErrorWidget.
      // Since the tree is in a broken state, adding the ErrorWidget would
      // cause more exceptions.
2804
      _debugReportException(ErrorSummary('while finalizing the widget tree'), e, stack);
2805 2806 2807
    } finally {
      Timeline.finishSync();
    }
2808
  }
2809

2810 2811
  /// Cause the entire subtree rooted at the given [Element] to be entirely
  /// rebuilt. This is used by development tools when the application code has
2812 2813
  /// changed and is being hot-reloaded, to cause the widget tree to pick up any
  /// changed implementations.
2814
  ///
2815
  /// This is expensive and should not be called except during development.
2816
  void reassemble(Element root) {
2817 2818 2819 2820
    Timeline.startSync('Dirty Element Tree');
    try {
      assert(root._parent == null);
      assert(root.owner == this);
2821
      root.reassemble();
2822 2823 2824
    } finally {
      Timeline.finishSync();
    }
2825
  }
2826 2827
}

2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840
/// An instantiation of a [Widget] at a particular location in the tree.
///
/// Widgets describe how to configure a subtree but the same widget can be used
/// to configure multiple subtrees simultaneously because widgets are immutable.
/// An [Element] represents the use of a widget to configure a specific location
/// in the tree. Over time, the widget associated with a given element can
/// change, for example, if the parent widget rebuilds and creates a new widget
/// for this location.
///
/// Elements form a tree. Most elements have a unique child, but some widgets
/// (e.g., subclasses of [RenderObjectElement]) can have multiple children.
///
/// Elements have the following lifecycle:
2841
///
2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
///  * The framework creates an element by calling [Widget.createElement] on the
///    widget that will be used as the element's initial configuration.
///  * The framework calls [mount] to add the newly created element to the tree
///    at a given slot in a given parent. The [mount] method is responsible for
///    inflating any child widgets and calling [attachRenderObject] as
///    necessary to attach any associated render objects to the render tree.
///  * At this point, the element is considered "active" and might appear on
///    screen.
///  * At some point, the parent might decide to change the widget used to
///    configure this element, for example because the parent rebuilt with new
///    state. When this happens, the framework will call [update] with the new
///    widget. The new widget will always have the same [runtimeType] and key as
///    old widget. If the parent wishes to change the [runtimeType] or key of
2855
///    the widget at this location in the tree, it can do so by unmounting this
2856 2857 2858 2859 2860 2861 2862 2863
///    element and inflating the new widget at this location.
///  * At some point, an ancestor might decide to remove this element (or an
///    intermediate ancestor) from the tree, which the ancestor does by calling
///    [deactivateChild] on itself. Deactivating the intermediate ancestor will
///    remove that element's render object from the render tree and add this
///    element to the [owner]'s list of inactive elements, causing the framework
///    to call [deactivate] on this element.
///  * At this point, the element is considered "inactive" and will not appear
2864
///    on screen. An element can remain in the inactive state only until
2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877
///    the end of the current animation frame. At the end of the animation
///    frame, any elements that are still inactive will be unmounted.
///  * If the element gets reincorporated into the tree (e.g., because it or one
///    of its ancestors has a global key that is reused), the framework will
///    remove the element from the [owner]'s list of inactive elements, call
///    [activate] on the element, and reattach the element's render object to
///    the render tree. (At this point, the element is again considered "active"
///    and might appear on screen.)
///  * If the element does not get reincorporated into the tree by the end of
///    the current animation frame, the framework will call [unmount] on the
///    element.
///  * At this point, the element is considered "defunct" and will not be
///    incorporated into the tree in the future.
2878
abstract class Element extends DiagnosticableTree implements BuildContext {
2879
  /// Creates an element that uses the given widget as its configuration.
2880 2881
  ///
  /// Typically called by an override of [Widget.createElement].
2882 2883 2884
  Element(Widget widget)
    : assert(widget != null),
      _widget = widget;
2885

2886 2887
  Element _parent;

2888 2889
  // Custom implementation of `operator ==` optimized for the ".of" pattern
  // used with `InheritedWidgets`.
2890
  @nonVirtual
2891
  @override
2892
  // ignore: avoid_equals_and_hash_code_on_mutable_classes
2893 2894 2895 2896 2897
  bool operator ==(Object other) => identical(this, other);

  // Custom implementation of hash code optimized for the ".of" pattern used
  // with `InheritedWidgets`.
  //
2898
  // `Element.dependOnInheritedWidgetOfExactType` relies heavily on hash-based
2899 2900 2901 2902 2903 2904 2905 2906
  // `Set` look-ups, putting this getter on the performance critical path.
  //
  // The value is designed to fit within the SMI representation. This makes
  // the cached value use less memory (one field and no extra heap objects) and
  // cheap to compare (no indirection).
  //
  // See also:
  //
2907
  //  * https://dart.dev/articles/dart-vm/numeric-computation, which
2908
  //    explains how numbers are represented in Dart.
2909
  @nonVirtual
2910
  @override
2911
  // ignore: avoid_equals_and_hash_code_on_mutable_classes
2912 2913 2914 2915
  int get hashCode => _cachedHash;
  final int _cachedHash = _nextHashCode = (_nextHashCode + 1) % 0xffffff;
  static int _nextHashCode = 1;

2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928
  /// Information set by parent to define where this child fits in its parent's
  /// child list.
  ///
  /// Subclasses of Element that only have one child should use null for
  /// the slot for that child.
  dynamic get slot => _slot;
  dynamic _slot;

  /// An integer that is guaranteed to be greater than the parent's, if any.
  /// The element at the root of the tree must have a depth greater than 0.
  int get depth => _depth;
  int _depth;

2929
  static int _sort(Element a, Element b) {
2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
    if (a.depth < b.depth)
      return -1;
    if (b.depth < a.depth)
      return 1;
    if (b.dirty && !a.dirty)
      return -1;
    if (a.dirty && !b.dirty)
      return 1;
    return 0;
  }

2941 2942 2943 2944 2945 2946 2947 2948 2949 2950
  // Return a numeric encoding of the specific `Element` concrete subtype.
  // This is used in `Element.updateChild` to determine if a hot reload modified the
  // superclass of a mounted element's configuration. The encoding of each `Element`
  // must match the corresponding `Widget` encoding in `Widget._debugConcreteSubtype`.
  static int _debugConcreteSubtype(Element element) {
    return element is StatefulElement ? 1 :
           element is StatelessElement ? 2 :
           0;
  }

2951
  /// The configuration for this element.
2952
  @override
2953 2954
  Widget get widget => _widget;
  Widget _widget;
2955

2956
  /// The object that manages the lifecycle of this element.
2957
  @override
2958
  BuildOwner get owner => _owner;
2959
  BuildOwner _owner;
2960

2961 2962
  bool _active = false;

2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973
  /// {@template flutter.widgets.reassemble}
  /// Called whenever the application is reassembled during debugging, for
  /// example during hot reload.
  ///
  /// This method should rerun any initialization logic that depends on global
  /// state, for example, image loading from asset bundles (since the asset
  /// bundle may have changed).
  ///
  /// This function will only be called during development. In release builds,
  /// the `ext.flutter.reassemble` hook is not available, and so this code will
  /// never execute.
2974 2975 2976 2977 2978 2979 2980 2981 2982
  ///
  /// Implementers should not rely on any ordering for hot reload source update,
  /// reassemble, and build methods after a hot reload has been initiated. It is
  /// possible that a [Timer] (e.g. an [Animation]) or a debugging session
  /// attached to the isolate could trigger a build with reloaded code _before_
  /// reassemble is called. Code that expects preconditions to be set by
  /// reassemble after a hot reload must be resilient to being called out of
  /// order, e.g. by fizzling instead of throwing. That said, once reassemble is
  /// called, build will be called after it at least once.
2983 2984 2985 2986 2987 2988 2989
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///  * [State.reassemble]
  ///  * [BindingBase.reassembleApplication]
  ///  * [Image], which uses this to reload images.
2990
  @mustCallSuper
2991 2992
  @protected
  void reassemble() {
2993
    markNeedsBuild();
2994
    visitChildren((Element child) {
2995
      child.reassemble();
2996 2997 2998
    });
  }

2999
  bool _debugIsInScope(Element target) {
3000 3001 3002 3003 3004 3005
    Element current = this;
    while (current != null) {
      if (target == current)
        return true;
      current = current._parent;
    }
3006 3007 3008
    return false;
  }

3009 3010 3011 3012 3013
  /// The render object at (or below) this location in the tree.
  ///
  /// If this object is a [RenderObjectElement], the render object is the one at
  /// this location in the tree. Otherwise, this getter will walk down the tree
  /// until it finds a [RenderObjectElement].
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
  RenderObject get renderObject {
    RenderObject result;
    void visit(Element element) {
      assert(result == null); // this verifies that there's only one child
      if (element is RenderObjectElement)
        result = element.renderObject;
      else
        element.visitChildren(visit);
    }
    visit(this);
    return result;
3025 3026
  }

3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079
  @override
  List<DiagnosticsNode> describeMissingAncestor({ @required Type expectedAncestorType }) {
    final List<DiagnosticsNode> information = <DiagnosticsNode>[];
    final List<Element> ancestors = <Element>[];
    visitAncestorElements((Element element) {
      ancestors.add(element);
      return true;
    });

    information.add(DiagnosticsProperty<Element>(
      'The specific widget that could not find a $expectedAncestorType ancestor was',
      this,
      style: DiagnosticsTreeStyle.errorProperty,
    ));

    if (ancestors.isNotEmpty) {
      information.add(describeElements('The ancestors of this widget were', ancestors));
    } else {
      information.add(ErrorDescription(
        'This widget is the root of the tree, so it has no '
        'ancestors, let alone a "$expectedAncestorType" ancestor.'
      ));
    }
    return information;
  }

  /// Returns a list of [Element]s from the current build context to the error report.
  static DiagnosticsNode describeElements(String name, Iterable<Element> elements) {
    return DiagnosticsBlock(
      name: name,
      children: elements.map<DiagnosticsNode>((Element element) => DiagnosticsProperty<Element>('', element)).toList(),
      allowTruncate: true,
    );
  }

  @override
  DiagnosticsNode describeElement(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) {
    return DiagnosticsProperty<Element>(name, this, style: style);
  }

  @override
  DiagnosticsNode describeWidget(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty}) {
    return DiagnosticsProperty<Element>(name, this, style: style);
  }

  @override
  DiagnosticsNode describeOwnershipChain(String name) {
    // TODO(jacobr): make this structured so clients can support clicks on
    // individual entries. For example, is this an iterable with arrows as
    // separators?
    return StringProperty(name, debugGetCreatorChain(10));
  }

3080 3081
  // This is used to verify that Element objects move through life in an
  // orderly fashion.
3082
  _ElementLifecycle _debugLifecycleState = _ElementLifecycle.initial;
3083

3084 3085
  /// Calls the argument for each child. Must be overridden by subclasses that
  /// support having children.
3086 3087 3088
  ///
  /// There is no guaranteed order in which the children will be visited, though
  /// it should be consistent over time.
3089 3090 3091 3092 3093
  ///
  /// Calling this during build is dangerous: the child list might still be
  /// being updated at that point, so the children might not be constructed yet,
  /// or might be old children that are going to be replaced. This method should
  /// only be called if it is provable that the children are available.
3094
  void visitChildren(ElementVisitor visitor) { }
3095

3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110
  /// Calls the argument for each child considered onstage.
  ///
  /// Classes like [Offstage] and [Overlay] override this method to hide their
  /// children.
  ///
  /// Being onstage affects the element's discoverability during testing when
  /// you use Flutter's [Finder] objects. For example, when you instruct the
  /// test framework to tap on a widget, by default the finder will look for
  /// onstage elements and ignore the offstage ones.
  ///
  /// The default implementation defers to [visitChildren] and therefore treats
  /// the element as onstage.
  ///
  /// See also:
  ///
3111 3112 3113 3114 3115
  ///  * [Offstage] widget that hides its children.
  ///  * [Finder] that skips offstage widgets by default.
  ///  * [RenderObject.visitChildrenForSemantics], in contrast to this method,
  ///    designed specifically for excluding parts of the UI from the semantics
  ///    tree.
3116
  void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
3117

3118
  /// Wrapper around [visitChildren] for [BuildContext].
3119
  @override
3120
  void visitChildElements(ElementVisitor visitor) {
3121 3122 3123
    assert(() {
      if (owner == null || !owner._debugStateLocked)
        return true;
3124 3125 3126
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('visitChildElements() called during build.'),
        ErrorDescription(
3127
          "The BuildContext.visitChildElements() method can't be called during "
3128 3129 3130
          'build because the child list is still being updated at that point, '
          'so the children might not be constructed yet, or might be old children '
          'that are going to be replaced.'
3131
        ),
3132
      ]);
3133
    }());
3134 3135 3136
    visitChildren(visitor);
  }

3137 3138
  /// Update the given child with the given new configuration.
  ///
3139 3140
  /// This method is the core of the widgets system. It is called each time we
  /// are to add, update, or remove a child based on an updated configuration.
3141
  ///
3142 3143
  /// If the `child` is null, and the `newWidget` is not null, then we have a new
  /// child for which we need to create an [Element], configured with `newWidget`.
3144
  ///
3145
  /// If the `newWidget` is null, and the `child` is not null, then we need to
3146 3147
  /// remove it because it no longer has a configuration.
  ///
3148 3149 3150 3151 3152
  /// If neither are null, then we need to update the `child`'s configuration to
  /// be the new configuration given by `newWidget`. If `newWidget` can be given
  /// to the existing child (as determined by [Widget.canUpdate]), then it is so
  /// given. Otherwise, the old child needs to be disposed and a new child
  /// created for the new configuration.
3153
  ///
3154 3155
  /// If both are null, then we don't have a child and won't have a child, so we
  /// do nothing.
3156
  ///
3157
  /// The [updateChild] method returns the new child, if it had to create one,
3158 3159
  /// or the child that was passed in, if it just had to update the child, or
  /// null, if it removed the child and did not replace it.
3160
  ///
3161
  /// The following table summarizes the above:
3162
  ///
3163 3164 3165 3166
  /// |                     | **newWidget == null**  | **newWidget != null**   |
  /// | :-----------------: | :--------------------- | :---------------------- |
  /// |  **child == null**  |  Returns null.         |  Returns new [Element]. |
  /// |  **child != null**  |  Old child is removed, returns null. | Old child updated if possible, returns child or new [Element]. |
3167
  @protected
3168 3169 3170
  Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
    if (newWidget == null) {
      if (child != null)
Hixie's avatar
Hixie committed
3171
        deactivateChild(child);
3172 3173
      return null;
    }
3174
    Element newChild;
3175
    if (child != null) {
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197
      bool hasSameSuperclass = true;
      // When the type of a widget is changed between Stateful and Stateless via
      // hot reload, the element tree will end up in a partially invalid state.
      // That is, if the widget was a StatefulWidget and is now a StatelessWidget,
      // then the element tree currently contains a StatefulElement that is incorrectly
      // referencing a StatelessWidget (and likewise with StatelessElement).
      //
      // To avoid crashing due to type errors, we need to gently guide the invalid
      // element out of the tree. To do so, we ensure that the `hasSameSuperclass` condition
      // returns false which prevents us from trying to update the existing element
      // incorrectly.
      //
      // For the case where the widget becomes Stateful, we also need to avoid
      // accessing `StatelessElement.widget` as the cast on the getter will
      // cause a type error to be thrown. Here we avoid that by short-circuiting
      // the `Widget.canUpdate` check once `hasSameSuperclass` is false.
      assert(() {
        final int oldElementClass = Element._debugConcreteSubtype(child);
        final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
        hasSameSuperclass = oldElementClass == newWidgetClass;
        return true;
      }());
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215
      if (hasSameSuperclass && child.widget == newWidget) {
        if (child.slot != newSlot)
          updateSlotForChild(child, newSlot);
        newChild = child;
      } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
        if (child.slot != newSlot)
          updateSlotForChild(child, newSlot);
        child.update(newWidget);
        assert(child.widget == newWidget);
        assert(() {
          child.owner._debugElementWasRebuilt(child);
          return true;
        }());
        newChild = child;
      } else {
        deactivateChild(child);
        assert(child._parent == null);
        newChild = inflateWidget(newWidget, newSlot);
3216
      }
3217 3218
    } else {
      newChild = inflateWidget(newWidget, newSlot);
3219
    }
3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231

    assert(() {
      if (child != null)
        _debugRemoveGlobalKeyReservation(child);
      final Key key = newWidget?.key;
      if (key is GlobalKey) {
        key._debugReserveFor(this, newChild);
      }
      return true;
    }());

    return newChild;
3232 3233
  }

3234 3235 3236 3237 3238
  /// Add this element to the tree in the given slot of the given parent.
  ///
  /// The framework calls this function when a newly created element is added to
  /// the tree for the first time. Use this method to initialize state that
  /// depends on having a parent. State that is independent of the parent can
3239
  /// more easily be initialized in the constructor.
3240 3241 3242
  ///
  /// This method transitions the element from the "initial" lifecycle state to
  /// the "active" lifecycle state.
3243
  @mustCallSuper
3244 3245 3246 3247
  void mount(Element parent, dynamic newSlot) {
    assert(_debugLifecycleState == _ElementLifecycle.initial);
    assert(widget != null);
    assert(_parent == null);
3248
    assert(parent == null || parent._debugLifecycleState == _ElementLifecycle.active);
3249 3250
    assert(slot == null);
    assert(depth == null);
3251
    assert(!_active);
3252 3253 3254
    _parent = parent;
    _slot = newSlot;
    _depth = _parent != null ? _parent.depth + 1 : 1;
3255
    _active = true;
3256 3257
    if (parent != null) // Only assign ownership if the parent is non-null
      _owner = parent.owner;
3258 3259
    final Key key = widget.key;
    if (key is GlobalKey) {
3260 3261
      key._register(this);
    }
3262
    _updateInheritance();
3263 3264 3265 3266
    assert(() {
      _debugLifecycleState = _ElementLifecycle.active;
      return true;
    }());
3267 3268
  }

3269 3270 3271
  void _debugRemoveGlobalKeyReservation(Element child) {
    GlobalKey._debugRemoveReservationFor(this, child);
  }
3272 3273 3274 3275 3276 3277 3278
  /// Change the widget used to configure this element.
  ///
  /// The framework calls this function when the parent wishes to use a
  /// different widget to configure this element. The new widget is guaranteed
  /// to have the same [runtimeType] as the old widget.
  ///
  /// This function is called only during the "active" lifecycle state.
3279
  @mustCallSuper
3280
  void update(covariant Widget newWidget) {
3281 3282 3283 3284 3285 3286 3287 3288 3289
    // This code is hot when hot reloading, so we try to
    // only call _AssertionError._evaluateAssertion once.
    assert(_debugLifecycleState == _ElementLifecycle.active
        && widget != null
        && newWidget != null
        && newWidget != widget
        && depth != null
        && _active
        && Widget.canUpdate(widget, newWidget));
3290 3291 3292 3293 3294 3295 3296 3297 3298 3299
    // This Element was told to update and we can now release all the global key
    // reservations of forgotten children. We cannot do this earlier because the
    // forgotten children still represent global key duplications if the element
    // never updates (the forgotten children are not removed from the tree
    // until the call to update happens)
    assert(() {
      _debugForgottenChildrenWithGlobalKey.forEach(_debugRemoveGlobalKeyReservation);
      _debugForgottenChildrenWithGlobalKey.clear();
      return true;
    }());
3300
    _widget = newWidget;
3301 3302
  }

3303 3304 3305 3306 3307
  /// Change the slot that the given child occupies in its parent.
  ///
  /// Called by [MultiChildRenderObjectElement], and other [RenderObjectElement]
  /// subclasses that have multiple children, when child moves from one position
  /// to another in this element's child list.
3308
  @protected
3309
  void updateSlotForChild(Element child, dynamic newSlot) {
3310
    assert(_debugLifecycleState == _ElementLifecycle.active);
3311 3312 3313 3314 3315 3316 3317 3318
    assert(child != null);
    assert(child._parent == this);
    void visit(Element element) {
      element._updateSlot(newSlot);
      if (element is! RenderObjectElement)
        element.visitChildren(visit);
    }
    visit(child);
3319 3320
  }

3321
  void _updateSlot(dynamic newSlot) {
3322
    assert(_debugLifecycleState == _ElementLifecycle.active);
3323 3324
    assert(widget != null);
    assert(_parent != null);
3325
    assert(_parent._debugLifecycleState == _ElementLifecycle.active);
3326
    assert(depth != null);
3327
    _slot = newSlot;
3328
  }
3329

3330
  void _updateDepth(int parentDepth) {
3331
    final int expectedDepth = parentDepth + 1;
3332 3333 3334
    if (_depth < expectedDepth) {
      _depth = expectedDepth;
      visitChildren((Element child) {
3335
        child._updateDepth(expectedDepth);
3336 3337 3338 3339
      });
    }
  }

3340 3341 3342
  /// Remove [renderObject] from the render tree.
  ///
  /// The default implementation of this function simply calls
3343
  /// [detachRenderObject] recursively on its child. The
3344 3345
  /// [RenderObjectElement.detachRenderObject] override does the actual work of
  /// removing [renderObject] from the render tree.
3346 3347
  ///
  /// This is called by [deactivateChild].
3348 3349 3350 3351 3352 3353 3354
  void detachRenderObject() {
    visitChildren((Element child) {
      child.detachRenderObject();
    });
    _slot = null;
  }

3355 3356 3357
  /// Add [renderObject] to the render tree at the location specified by [slot].
  ///
  /// The default implementation of this function simply calls
3358
  /// [attachRenderObject] recursively on its child. The
3359 3360
  /// [RenderObjectElement.attachRenderObject] override does the actual work of
  /// adding [renderObject] to the render tree.
3361 3362 3363 3364 3365 3366 3367 3368
  void attachRenderObject(dynamic newSlot) {
    assert(_slot == null);
    visitChildren((Element child) {
      child.attachRenderObject(newSlot);
    });
    _slot = newSlot;
  }

3369
  Element _retakeInactiveElement(GlobalKey key, Widget newWidget) {
3370 3371 3372 3373 3374 3375
    // The "inactivity" of the element being retaken here may be forward-looking: if
    // we are taking an element with a GlobalKey from an element that currently has
    // it as a child, then we know that that element will soon no longer have that
    // element as a child. The only way that assumption could be false is if the
    // global key is being duplicated, and we'll try to track that using the
    // _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans call below.
3376
    final Element element = key._currentElement;
3377 3378
    if (element == null)
      return null;
3379
    if (!Widget.canUpdate(element.widget, newWidget))
3380
      return null;
3381 3382
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle)
3383
        debugPrint('Attempting to take $element from ${element._parent ?? "inactive elements list"} to put in $this.');
3384
      return true;
3385
    }());
3386 3387
    final Element parent = element._parent;
    if (parent != null) {
3388 3389
      assert(() {
        if (parent == this) {
3390
          throw FlutterError.fromParts(<DiagnosticsNode>[
3391
            ErrorSummary("A GlobalKey was used multiple times inside one widget's child list."),
3392 3393 3394 3395
            DiagnosticsProperty<GlobalKey>('The offending GlobalKey was', key),
            parent.describeElement('The parent of the widgets with that key was'),
            element.describeElement('The first child to get instantiated with that key became'),
            DiagnosticsProperty<Widget>('The second child that was to be instantiated with that key was', widget, style: DiagnosticsTreeStyle.errorProperty),
3396
            ErrorDescription('A GlobalKey can only be specified on one widget at a time in the widget tree.'),
3397
          ]);
3398 3399 3400 3401 3402 3403
        }
        parent.owner._debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(
          parent,
          key,
        );
        return true;
3404
      }());
3405
      parent.forgetChild(element);
3406
      parent.deactivateChild(element);
3407
    }
3408
    assert(element._parent == null);
3409
    owner._inactiveElements.remove(element);
3410 3411 3412
    return element;
  }

3413 3414
  /// Create an element for the given widget and add it as a child of this
  /// element in the given slot.
3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426
  ///
  /// This method is typically called by [updateChild] but can be called
  /// directly by subclasses that need finer-grained control over creating
  /// elements.
  ///
  /// If the given widget has a global key and an element already exists that
  /// has a widget with that global key, this function will reuse that element
  /// (potentially grafting it from another location in the tree or reactivating
  /// it from the list of inactive elements) rather than creating a new element.
  ///
  /// The element returned by this function will already have been mounted and
  /// will be in the "active" lifecycle state.
3427
  @protected
Hixie's avatar
Hixie committed
3428
  Element inflateWidget(Widget newWidget, dynamic newSlot) {
3429
    assert(newWidget != null);
3430
    final Key key = newWidget.key;
3431
    if (key is GlobalKey) {
3432
      final Element newChild = _retakeInactiveElement(key, newWidget);
3433 3434
      if (newChild != null) {
        assert(newChild._parent == null);
3435 3436 3437 3438
        assert(() {
          _debugCheckForCycles(newChild);
          return true;
        }());
3439
        newChild._activateWithParent(this, newSlot);
3440
        final Element updatedChild = updateChild(newChild, newWidget, newSlot);
3441 3442 3443 3444
        assert(newChild == updatedChild);
        return updatedChild;
      }
    }
3445
    final Element newChild = newWidget.createElement();
3446 3447 3448 3449
    assert(() {
      _debugCheckForCycles(newChild);
      return true;
    }());
3450 3451 3452 3453 3454
    newChild.mount(this, newSlot);
    assert(newChild._debugLifecycleState == _ElementLifecycle.active);
    return newChild;
  }

3455 3456 3457 3458 3459 3460 3461 3462
  void _debugCheckForCycles(Element newChild) {
    assert(newChild._parent == null);
    assert(() {
      Element node = this;
      while (node._parent != null)
        node = node._parent;
      assert(node != newChild); // indicates we are about to create a cycle
      return true;
3463
    }());
3464 3465
  }

3466 3467
  /// Move the given element to the list of inactive elements and detach its
  /// render object from the render tree.
3468 3469 3470 3471 3472
  ///
  /// This method stops the given element from being a child of this element by
  /// detaching its render object from the render tree and moving the element to
  /// the list of inactive elements.
  ///
3473 3474
  /// This method (indirectly) calls [deactivate] on the child.
  ///
3475
  /// The caller is responsible for removing the child from its child model.
3476 3477
  /// Typically [deactivateChild] is called by the element itself while it is
  /// updating its child model; however, during [GlobalKey] reparenting, the new
3478 3479
  /// parent proactively calls the old parent's [deactivateChild], first using
  /// [forgetChild] to cause the old parent to update its child model.
3480
  @protected
Hixie's avatar
Hixie committed
3481
  void deactivateChild(Element child) {
3482 3483 3484
    assert(child != null);
    assert(child._parent == this);
    child._parent = null;
3485
    child.detachRenderObject();
3486
    owner._inactiveElements.add(child); // this eventually calls child.deactivate()
3487 3488 3489 3490 3491 3492
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle) {
        if (child.widget.key is GlobalKey)
          debugPrint('Deactivated $child (keyed child of $this)');
      }
      return true;
3493
    }());
3494
  }
3495

3496 3497 3498 3499
  // The children that have been forgotten by forgetChild. This will be used in
  // [update] to remove the global key reservations of forgotten children.
  final Set<Element> _debugForgottenChildrenWithGlobalKey = HashSet<Element>();

3500 3501 3502 3503 3504 3505
  /// Remove the given child from the element's child list, in preparation for
  /// the child being reused elsewhere in the element tree.
  ///
  /// This updates the child model such that, e.g., [visitChildren] does not
  /// walk that child anymore.
  ///
3506 3507
  /// The element will still have a valid parent when this is called. After this
  /// is called, [deactivateChild] is called to sever the link to this object.
3508 3509 3510
  ///
  /// The [update] is responsible for updating or creating the new child that
  /// will replace this [child].
3511
  @protected
3512
  @mustCallSuper
3513
  void forgetChild(Element child) {
3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524
    // This method is called on the old parent when the given child (with a
    // global key) is given a new parent. We cannot remove the global key
    // reservation directly in this method because the forgotten child is not
    // removed from the tree until this Element is updated in [update]. If
    // [update] is never called, the forgotten child still represents a global
    // key duplication that we need to catch.
    assert(() {
      if (child.widget.key is GlobalKey)
        _debugForgottenChildrenWithGlobalKey.add(child);
      return true;
    }());
3525
  }
3526

3527
  void _activateWithParent(Element parent, dynamic newSlot) {
3528 3529
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
    _parent = parent;
3530 3531 3532 3533
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle)
        debugPrint('Reactivating $this (now child of $_parent).');
      return true;
3534
    }());
3535 3536
    _updateDepth(_parent.depth);
    _activateRecursively(this);
3537 3538 3539 3540
    attachRenderObject(newSlot);
    assert(_debugLifecycleState == _ElementLifecycle.active);
  }

3541 3542 3543 3544 3545 3546 3547
  static void _activateRecursively(Element element) {
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
    element.activate();
    assert(element._debugLifecycleState == _ElementLifecycle.active);
    element.visitChildren(_activateRecursively);
  }

3548 3549 3550 3551 3552 3553 3554 3555
  /// Transition from the "inactive" to the "active" lifecycle state.
  ///
  /// The framework calls this method when a previously deactivated element has
  /// been reincorporated into the tree. The framework does not call this method
  /// the first time an element becomes active (i.e., from the "initial"
  /// lifecycle state). Instead, the framework calls [mount] in that situation.
  ///
  /// See the lifecycle documentation for [Element] for additional information.
3556
  @mustCallSuper
3557
  void activate() {
3558 3559
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
    assert(widget != null);
3560
    assert(owner != null);
3561 3562
    assert(depth != null);
    assert(!_active);
3563
    final bool hadDependencies = (_dependencies != null && _dependencies.isNotEmpty) || _hadUnsatisfiedDependencies;
3564
    _active = true;
3565 3566 3567
    // We unregistered our dependencies in deactivate, but never cleared the list.
    // Since we're going to be reused, let's clear our list now.
    _dependencies?.clear();
3568
    _hadUnsatisfiedDependencies = false;
3569
    _updateInheritance();
3570 3571 3572 3573
    assert(() {
      _debugLifecycleState = _ElementLifecycle.active;
      return true;
    }());
3574 3575 3576
    if (_dirty)
      owner.scheduleBuildFor(this);
    if (hadDependencies)
3577
      didChangeDependencies();
3578 3579
  }

3580 3581 3582 3583 3584 3585 3586 3587 3588
  /// Transition from the "active" to the "inactive" lifecycle state.
  ///
  /// The framework calls this method when a previously active element is moved
  /// to the list of inactive elements. While in the inactive state, the element
  /// will not appear on screen. The element can remain in the inactive state
  /// only until the end of the current animation frame. At the end of the
  /// animation frame, if the element has not be reactivated, the framework will
  /// unmount the element.
  ///
3589 3590
  /// This is (indirectly) called by [deactivateChild].
  ///
3591
  /// See the lifecycle documentation for [Element] for additional information.
3592
  @mustCallSuper
3593 3594
  void deactivate() {
    assert(_debugLifecycleState == _ElementLifecycle.active);
3595
    assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
3596
    assert(depth != null);
3597
    assert(_active);
3598
    if (_dependencies != null && _dependencies.isNotEmpty) {
3599
      for (final InheritedElement dependency in _dependencies)
3600
        dependency._dependents.remove(this);
3601 3602 3603
      // For expediency, we don't actually clear the list here, even though it's
      // no longer representative of what we are registered with. If we never
      // get re-used, it doesn't matter. If we do, then we'll clear the list in
3604 3605 3606
      // activate(). The benefit of this is that it allows Element's activate()
      // implementation to decide whether to rebuild based on whether we had
      // dependencies here.
3607
    }
3608
    _inheritedWidgets = null;
3609
    _active = false;
3610 3611 3612 3613
    assert(() {
      _debugLifecycleState = _ElementLifecycle.inactive;
      return true;
    }());
3614 3615
  }

3616 3617 3618
  /// Called, in debug mode, after children have been deactivated (see [deactivate]).
  ///
  /// This method is not called in release builds.
3619
  @mustCallSuper
3620 3621 3622 3623
  void debugDeactivated() {
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
  }

3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634
  /// Transition from the "inactive" to the "defunct" lifecycle state.
  ///
  /// Called when the framework determines that an inactive element will never
  /// be reactivated. At the end of each animation frame, the framework calls
  /// [unmount] on any remaining inactive elements, preventing inactive elements
  /// from remaining inactive for longer than a single animation frame.
  ///
  /// After this function is called, the element will not be incorporated into
  /// the tree again.
  ///
  /// See the lifecycle documentation for [Element] for additional information.
3635
  @mustCallSuper
3636
  void unmount() {
3637
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
3638
    assert(_widget != null); // Use the private property to avoid a CastError during hot reload.
3639
    assert(depth != null);
3640
    assert(!_active);
3641 3642
    // Use the private property to avoid a CastError during hot reload.
    final Key key = _widget.key;
3643
    if (key is GlobalKey) {
3644 3645
      key._unregister(this);
    }
3646 3647 3648 3649
    assert(() {
      _debugLifecycleState = _ElementLifecycle.defunct;
      return true;
    }());
3650 3651
  }

3652
  @override
Hixie's avatar
Hixie committed
3653 3654
  RenderObject findRenderObject() => renderObject;

3655 3656 3657 3658
  @override
  Size get size {
    assert(() {
      if (_debugLifecycleState != _ElementLifecycle.active) {
3659 3660 3661 3662 3663 3664 3665 3666 3667
        // TODO(jacobr): is this a good separation into contract and violation?
        // I have added a line of white space.
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size of inactive element.'),
          ErrorDescription(
            'In order for an element to have a valid size, the element must be '
            'active, which means it is part of the tree.\n'
            'Instead, this element is in the $_debugLifecycleState state.'
          ),
3668
          describeElement('The size getter was called for the following element'),
3669
        ]);
3670 3671
      }
      if (owner._debugBuilding) {
3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size during build.'),
          ErrorDescription(
            'The size of this render object has not yet been determined because '
            'the framework is still in the process of building widgets, which '
            'means the render tree for this frame has not yet been determined. '
            'The size getter should only be called from paint callbacks or '
            'interaction event handlers (e.g. gesture callbacks).'
          ),
          ErrorSpacer(),
          ErrorHint(
            'If you need some sizing information during build to decide which '
            'widgets to build, consider using a LayoutBuilder widget, which can '
            'tell you the layout constraints at a given location in the tree. See '
            '<https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html> '
            'for more details.'
          ),
          ErrorSpacer(),
3690
          describeElement('The size getter was called for the following element'),
3691
        ]);
3692 3693
      }
      return true;
3694
    }());
3695 3696 3697
    final RenderObject renderObject = findRenderObject();
    assert(() {
      if (renderObject == null) {
3698 3699 3700 3701 3702 3703 3704 3705 3706
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size without a render object.'),
          ErrorHint(
            'In order for an element to have a valid size, the element must have '
            'an associated render object. This element does not have an associated '
            'render object, which typically means that the size getter was called '
            'too early in the pipeline (e.g., during the build phase) before the '
            'framework has created the render tree.'
          ),
3707
          describeElement('The size getter was called for the following element'),
3708
        ]);
3709
      }
3710
      if (renderObject is RenderSliver) {
3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size from a RenderSliver.'),
          ErrorHint(
            'The render object associated with this element is a '
            '${renderObject.runtimeType}, which is a subtype of RenderSliver. '
            'Slivers do not have a size per se. They have a more elaborate '
            'geometry description, which can be accessed by calling '
            'findRenderObject and then using the "geometry" getter on the '
            'resulting object.'
          ),
          describeElement('The size getter was called for the following element'),
          renderObject.describeForError('The associated render sliver was'),
        ]);
3724
      }
3725
      if (renderObject is! RenderBox) {
3726 3727 3728 3729 3730 3731 3732 3733 3734
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size from a render object that is not a RenderBox.'),
          ErrorHint(
            'Instead of being a subtype of RenderBox, the render object associated '
            'with this element is a ${renderObject.runtimeType}. If this type of '
            'render object does have a size, consider calling findRenderObject '
            'and extracting its size manually.'
          ),
          describeElement('The size getter was called for the following element'),
3735
          renderObject.describeForError('The associated render object was'),
3736
        ]);
3737
      }
3738
      final RenderBox box = renderObject as RenderBox;
3739
      if (!box.hasSize) {
3740 3741 3742 3743 3744 3745 3746 3747 3748 3749
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size from a render object that has not been through layout.'),
          ErrorHint(
            'The size of this render object has not yet been determined because '
            'this render object has not yet been through layout, which typically '
            'means that the size getter was called too early in the pipeline '
            '(e.g., during the build phase) before the framework has determined '
           'the size and position of the render objects during layout.'
          ),
          describeElement('The size getter was called for the following element'),
3750
          box.describeForError('The render object from which the size was to be obtained was'),
3751
        ]);
3752 3753
      }
      if (box.debugNeedsLayout) {
3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot get size from a render object that has been marked dirty for layout.'),
          ErrorHint(
            'The size of this render object is ambiguous because this render object has '
            'been modified since it was last laid out, which typically means that the size '
            'getter was called too early in the pipeline (e.g., during the build phase) '
            'before the framework has determined the size and position of the render '
            'objects during layout.'
          ),
          describeElement('The size getter was called for the following element'),
          box.describeForError('The render object from which the size was to be obtained was'),
          ErrorHint(
            'Consider using debugPrintMarkNeedsLayoutStacks to determine why the render '
            'object in question is dirty, if you did not expect this.'
          ),
        ]);
3770 3771
      }
      return true;
3772
    }());
3773 3774 3775 3776 3777
    if (renderObject is RenderBox)
      return renderObject.size;
    return null;
  }

3778
  Map<Type, InheritedElement> _inheritedWidgets;
3779
  Set<InheritedElement> _dependencies;
3780
  bool _hadUnsatisfiedDependencies = false;
3781

3782
  bool _debugCheckStateIsActiveForAncestorLookup() {
3783 3784
    assert(() {
      if (_debugLifecycleState != _ElementLifecycle.active) {
3785
        throw FlutterError.fromParts(<DiagnosticsNode>[
3786
          ErrorSummary("Looking up a deactivated widget's ancestor is unsafe."),
3787
          ErrorDescription(
3788
            "At this point the state of the widget's element tree is no longer "
3789 3790 3791
            'stable.'
          ),
          ErrorHint(
3792
            "To safely refer to a widget's ancestor in its dispose() method, "
3793
            'save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() '
3794
            "in the widget's didChangeDependencies() method."
3795
          ),
3796
        ]);
3797 3798
      }
      return true;
3799
    }());
3800 3801 3802
    return true;
  }

3803 3804 3805 3806 3807
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use dependOnInheritedElement instead. '
    'This feature was deprecated after v1.12.1.'
  )
3808
  @override
3809
  InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect }) {
3810 3811 3812 3813 3814
    return dependOnInheritedElement(ancestor, aspect: aspect);
  }

  @override
  InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect }) {
3815
    assert(ancestor != null);
3816
    _dependencies ??= HashSet<InheritedElement>();
3817 3818 3819 3820 3821
    _dependencies.add(ancestor);
    ancestor.updateDependencies(this, aspect);
    return ancestor.widget;
  }

3822 3823 3824 3825 3826
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use dependOnInheritedWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
3827 3828
  @override
  InheritedWidget inheritFromWidgetOfExactType(Type targetType, { Object aspect }) {
3829
    assert(_debugCheckStateIsActiveForAncestorLookup());
3830
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
3831 3832
    if (ancestor != null) {
      assert(ancestor is InheritedElement);
3833
      return inheritFromElement(ancestor, aspect: aspect);
3834
    }
3835
    _hadUnsatisfiedDependencies = true;
3836
    return null;
Hixie's avatar
Hixie committed
3837 3838
  }

3839 3840 3841 3842 3843 3844
  @override
  T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object aspect}) {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];
    if (ancestor != null) {
      assert(ancestor is InheritedElement);
3845
      return dependOnInheritedElement(ancestor, aspect: aspect) as T;
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
    }
    _hadUnsatisfiedDependencies = true;
    return null;
  }

  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use getElementForInheritedWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
Matt Perry's avatar
Matt Perry committed
3856 3857
  @override
  InheritedElement ancestorInheritedElementForWidgetOfExactType(Type targetType) {
3858
    assert(_debugCheckStateIsActiveForAncestorLookup());
3859
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
Matt Perry's avatar
Matt Perry committed
3860 3861 3862
    return ancestor;
  }

3863 3864 3865 3866 3867 3868 3869
  @override
  InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];
    return ancestor;
  }

3870
  void _updateInheritance() {
3871
    assert(_active);
3872 3873 3874
    _inheritedWidgets = _parent?._inheritedWidgets;
  }

3875 3876 3877 3878 3879
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorWidgetOfExactType instead. '
    'This feature was deprecated after v1.12.1.'
  )
3880
  @override
Ian Hickson's avatar
Ian Hickson committed
3881
  Widget ancestorWidgetOfExactType(Type targetType) {
3882
    assert(_debugCheckStateIsActiveForAncestorLookup());
3883 3884 3885 3886
    Element ancestor = _parent;
    while (ancestor != null && ancestor.widget.runtimeType != targetType)
      ancestor = ancestor._parent;
    return ancestor?.widget;
3887 3888
  }

3889 3890 3891 3892 3893 3894
  @override
  T findAncestorWidgetOfExactType<T extends Widget>() {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    Element ancestor = _parent;
    while (ancestor != null && ancestor.widget.runtimeType != T)
      ancestor = ancestor._parent;
3895
    return ancestor?.widget as T;
3896 3897 3898 3899 3900 3901 3902
  }

  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorStateOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
3903
  @override
Ian Hickson's avatar
Ian Hickson committed
3904
  State ancestorStateOfType(TypeMatcher matcher) {
3905
    assert(_debugCheckStateIsActiveForAncestorLookup());
Hixie's avatar
Hixie committed
3906 3907
    Element ancestor = _parent;
    while (ancestor != null) {
3908
      if (ancestor is StatefulElement && matcher.check(ancestor.state))
Hixie's avatar
Hixie committed
3909 3910 3911
        break;
      ancestor = ancestor._parent;
    }
3912
    final StatefulElement statefulAncestor = ancestor as StatefulElement;
Hixie's avatar
Hixie committed
3913 3914
    return statefulAncestor?.state;
  }
3915

3916 3917 3918 3919 3920 3921 3922 3923 3924
  @override
  T findAncestorStateOfType<T extends State<StatefulWidget>>() {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    Element ancestor = _parent;
    while (ancestor != null) {
      if (ancestor is StatefulElement && ancestor.state is T)
        break;
      ancestor = ancestor._parent;
    }
3925 3926
    final StatefulElement statefulAncestor = ancestor as StatefulElement;
    return statefulAncestor?.state as T;
3927 3928 3929 3930 3931 3932 3933
  }

  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findRootAncestorStateOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
3934 3935
  @override
  State rootAncestorStateOfType(TypeMatcher matcher) {
3936
    assert(_debugCheckStateIsActiveForAncestorLookup());
3937 3938 3939 3940 3941 3942 3943 3944 3945 3946
    Element ancestor = _parent;
    StatefulElement statefulAncestor;
    while (ancestor != null) {
      if (ancestor is StatefulElement && matcher.check(ancestor.state))
        statefulAncestor = ancestor;
      ancestor = ancestor._parent;
    }
    return statefulAncestor?.state;
  }

3947 3948 3949 3950 3951 3952 3953 3954 3955 3956
  @override
  T findRootAncestorStateOfType<T extends State<StatefulWidget>>() {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    Element ancestor = _parent;
    StatefulElement statefulAncestor;
    while (ancestor != null) {
      if (ancestor is StatefulElement && ancestor.state is T)
        statefulAncestor = ancestor;
      ancestor = ancestor._parent;
    }
3957
    return statefulAncestor?.state as T;
3958 3959 3960 3961 3962 3963 3964
  }

  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use findAncestorRenderObjectOfType instead. '
    'This feature was deprecated after v1.12.1.'
  )
3965
  @override
Ian Hickson's avatar
Ian Hickson committed
3966
  RenderObject ancestorRenderObjectOfType(TypeMatcher matcher) {
3967
    assert(_debugCheckStateIsActiveForAncestorLookup());
3968 3969
    Element ancestor = _parent;
    while (ancestor != null) {
Ian Hickson's avatar
Ian Hickson committed
3970
      if (ancestor is RenderObjectElement && matcher.check(ancestor.renderObject))
3971
        return ancestor.renderObject;
3972 3973
      ancestor = ancestor._parent;
    }
3974
    return null;
3975 3976
  }

3977 3978 3979 3980 3981 3982
  @override
  T findAncestorRenderObjectOfType<T extends RenderObject>() {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    Element ancestor = _parent;
    while (ancestor != null) {
      if (ancestor is RenderObjectElement && ancestor.renderObject is T)
3983
        return ancestor.renderObject as T;
3984 3985
      ancestor = ancestor._parent;
    }
3986
    return null;
3987 3988
  }

3989
  @override
3990
  void visitAncestorElements(bool visitor(Element element)) {
3991
    assert(_debugCheckStateIsActiveForAncestorLookup());
3992 3993 3994
    Element ancestor = _parent;
    while (ancestor != null && visitor(ancestor))
      ancestor = ancestor._parent;
3995 3996
  }

3997 3998
  /// Called when a dependency of this element changes.
  ///
3999
  /// The [dependOnInheritedWidgetOfExactType] registers this element as depending on
4000 4001 4002 4003 4004
  /// inherited information of the given type. When the information of that type
  /// changes at this location in the tree (e.g., because the [InheritedElement]
  /// updated to a new [InheritedWidget] and
  /// [InheritedWidget.updateShouldNotify] returned true), the framework calls
  /// this function to notify this element of the change.
4005
  @mustCallSuper
4006 4007
  void didChangeDependencies() {
    assert(_active); // otherwise markNeedsBuild is a no-op
4008
    assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
4009 4010
    markNeedsBuild();
  }
4011

4012
  bool _debugCheckOwnerBuildTargetExists(String methodName) {
4013 4014
    assert(() {
      if (owner._debugCurrentBuildTarget == null) {
4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            '$methodName for ${widget.runtimeType} was called at an '
            'inappropriate time.'
          ),
          ErrorDescription('It may only be called while the widgets are being built.'),
          ErrorHint(
            'A possible cause of this error is when $methodName is called during '
            'one of:\n'
            ' * network I/O event\n'
            ' * file I/O event\n'
            ' * timer\n'
            ' * microtask (caused by Future.then, async/await, scheduleMicrotask)'
4028
          ),
4029
        ]);
4030 4031
      }
      return true;
4032 4033
    }());
    return true;
4034 4035
  }

4036 4037 4038
  /// Returns a description of what caused this element to be created.
  ///
  /// Useful for debugging the source of an element.
4039
  String debugGetCreatorChain(int limit) {
4040
    final List<String> chain = <String>[];
4041 4042 4043 4044 4045 4046 4047
    Element node = this;
    while (chain.length < limit && node != null) {
      chain.add(node.toStringShort());
      node = node._parent;
    }
    if (node != null)
      chain.add('\u22EF');
4048
    return chain.join(' \u2190 ');
4049 4050
  }

4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064
  /// Returns the parent chain from this element back to the root of the tree.
  ///
  /// Useful for debug display of a tree of Elements with only nodes in the path
  /// from the root to this Element expanded.
  List<Element> debugGetDiagnosticChain() {
    final List<Element> chain = <Element>[this];
    Element node = _parent;
    while (node != null) {
      chain.add(node);
      node = node._parent;
    }
    return chain;
  }

4065
  /// A short, textual description of this element.
4066 4067
  @override
  String toStringShort() {
4068
    return widget != null ? widget.toStringShort() : '[${objectRuntimeType(this, 'Element')}]';
4069 4070
  }

4071 4072 4073 4074 4075 4076 4077 4078 4079
  @override
  DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style }) {
    return _ElementDiagnosticableTreeNode(
      name: name,
      value: this,
      style: style,
    );
  }

4080
  @override
4081 4082 4083
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle= DiagnosticsTreeStyle.dense;
4084 4085
    properties.add(ObjectFlagProperty<int>('depth', depth, ifNull: 'no depth'));
    properties.add(ObjectFlagProperty<Widget>('widget', widget, ifNull: 'no widget'));
4086
    if (widget != null) {
4087
      properties.add(DiagnosticsProperty<Key>('key', widget?.key, showName: false, defaultValue: null, level: DiagnosticLevel.hidden));
4088
      widget.debugFillProperties(properties);
4089
    }
4090
    properties.add(FlagProperty('dirty', value: dirty, ifTrue: 'dirty'));
4091 4092 4093 4094 4095 4096
    if (_dependencies != null && _dependencies.isNotEmpty) {
      final List<DiagnosticsNode> diagnosticsDependencies = _dependencies
        .map((InheritedElement element) => element.widget.toDiagnosticsNode(style: DiagnosticsTreeStyle.sparse))
        .toList();
      properties.add(DiagnosticsProperty<List<DiagnosticsNode>>('dependencies', diagnosticsDependencies));
    }
4097
  }
4098

4099
  @override
4100 4101 4102
  List<DiagnosticsNode> debugDescribeChildren() {
    final List<DiagnosticsNode> children = <DiagnosticsNode>[];
    visitChildren((Element child) {
4103 4104 4105
      if (child != null) {
        children.add(child.toDiagnosticsNode());
      } else {
4106
        children.add(DiagnosticsNode.message('<null child>'));
4107
      }
4108 4109
    });
    return children;
4110
  }
4111

4112 4113 4114
  /// Returns true if the element has been marked as needing rebuilding.
  bool get dirty => _dirty;
  bool _dirty = true;
4115

4116 4117 4118 4119
  // Whether this is in owner._dirtyElements. This is used to know whether we
  // should be adding the element back into the list when it's reactivated.
  bool _inDirtyList = false;

4120 4121 4122
  // Whether we've already built or not. Set in [rebuild].
  bool _debugBuiltOnce = false;

4123
  // We let widget authors call setState from initState, didUpdateWidget, and
4124 4125
  // build even when state is locked because its convenient and a no-op anyway.
  // This flag ensures that this convenience is only allowed on the element
4126
  // currently undergoing initState, didUpdateWidget, or build.
4127 4128 4129 4130
  bool _debugAllowIgnoredCallsToMarkNeedsBuild = false;
  bool _debugSetAllowIgnoredCallsToMarkNeedsBuild(bool value) {
    assert(_debugAllowIgnoredCallsToMarkNeedsBuild == !value);
    _debugAllowIgnoredCallsToMarkNeedsBuild = value;
4131 4132 4133
    return true;
  }

4134 4135 4136 4137
  /// Marks the element as dirty and adds it to the global list of widgets to
  /// rebuild in the next frame.
  ///
  /// Since it is inefficient to build an element twice in one frame,
4138 4139
  /// applications and widgets should be structured so as to only mark
  /// widgets dirty during event handlers before the frame begins, not during
4140 4141 4142
  /// the build itself.
  void markNeedsBuild() {
    assert(_debugLifecycleState != _ElementLifecycle.defunct);
4143 4144
    if (!_active)
      return;
4145
    assert(owner != null);
4146
    assert(_debugLifecycleState == _ElementLifecycle.active);
Hixie's avatar
Hixie committed
4147
    assert(() {
4148
      if (owner._debugBuilding) {
4149 4150
        assert(owner._debugCurrentBuildTarget != null);
        assert(owner._debugStateLocked);
4151
        if (_debugIsInScope(owner._debugCurrentBuildTarget))
Hixie's avatar
Hixie committed
4152
          return true;
4153
        if (!_debugAllowIgnoredCallsToMarkNeedsBuild) {
4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166
          final List<DiagnosticsNode> information = <DiagnosticsNode>[
            ErrorSummary('setState() or markNeedsBuild() called during build.'),
            ErrorDescription(
              'This ${widget.runtimeType} widget cannot be marked as needing to build because the framework '
              'is already in the process of building widgets.  A widget can be marked as '
              'needing to be built during the build phase only if one of its ancestors '
              'is currently building. This exception is allowed because the framework '
              'builds parent widgets before children, which means a dirty descendant '
              'will always be built. Otherwise, the framework might not visit this '
              'widget during this build phase.'
            ),
            describeElement(
              'The widget on which setState() or markNeedsBuild() was called was',
4167
            ),
4168 4169 4170 4171
          ];
          if (owner._debugCurrentBuildTarget != null)
            information.add(owner._debugCurrentBuildTarget.describeWidget('The widget which was currently being built when the offending call was made was'));
          throw FlutterError.fromParts(information);
4172 4173 4174 4175
        }
        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)
      } else if (owner._debugStateLocked) {
        assert(!_debugAllowIgnoredCallsToMarkNeedsBuild);
4176 4177 4178 4179 4180 4181
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),
          ErrorDescription(
            'This ${widget.runtimeType} widget cannot be marked as needing to build '
            'because the framework is locked.'
          ),
4182
          describeElement('The widget on which setState() or markNeedsBuild() was called was'),
4183
        ]);
4184 4185
      }
      return true;
4186
    }());
4187 4188 4189
    if (dirty)
      return;
    _dirty = true;
4190
    owner.scheduleBuildFor(this);
4191
  }
4192

4193 4194 4195
  /// Called by the [BuildOwner] when [BuildOwner.scheduleBuildFor] has been
  /// called to mark this element dirty, by [mount] when the element is first
  /// built, and by [update] when the widget has changed.
4196 4197
  void rebuild() {
    assert(_debugLifecycleState != _ElementLifecycle.initial);
4198
    if (!_active || !_dirty)
4199
      return;
4200
    assert(() {
4201 4202 4203
      if (debugOnRebuildDirtyWidget != null) {
        debugOnRebuildDirtyWidget(this, _debugBuiltOnce);
      }
4204 4205 4206 4207 4208 4209 4210 4211
      if (debugPrintRebuildDirtyWidgets) {
        if (!_debugBuiltOnce) {
          debugPrint('Building $this');
          _debugBuiltOnce = true;
        } else {
          debugPrint('Rebuilding $this');
        }
      }
4212
      return true;
4213
    }());
4214
    assert(_debugLifecycleState == _ElementLifecycle.active);
4215
    assert(owner._debugStateLocked);
4216
    Element debugPreviousBuildTarget;
4217
    assert(() {
4218 4219
      debugPreviousBuildTarget = owner._debugCurrentBuildTarget;
      owner._debugCurrentBuildTarget = this;
4220
      return true;
4221
    }());
4222 4223
    performRebuild();
    assert(() {
4224 4225
      assert(owner._debugCurrentBuildTarget == this);
      owner._debugCurrentBuildTarget = debugPreviousBuildTarget;
4226
      return true;
4227
    }());
4228
    assert(!_dirty);
4229 4230
  }

4231
  /// Called by rebuild() after the appropriate checks have been made.
4232
  @protected
4233
  void performRebuild();
4234
}
4235

4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252
class _ElementDiagnosticableTreeNode extends DiagnosticableTreeNode {
  _ElementDiagnosticableTreeNode({
    String name,
    @required Element value,
    @required DiagnosticsTreeStyle style,
    this.stateful = false,
  }) : super(
    name: name,
    value: value,
    style: style,
  );

  final bool stateful;

  @override
  Map<String, Object> toJsonMap(DiagnosticsSerializationDelegate delegate) {
    final Map<String, Object> json = super.toJsonMap(delegate);
4253
    final Element element = value as Element;
4254 4255 4256 4257 4258 4259
    json['widgetRuntimeType'] = element.widget?.runtimeType?.toString();
    json['stateful'] = stateful;
    return json;
  }
}

4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271
/// Signature for the constructor that is called when an error occurs while
/// building a widget.
///
/// The argument provides information regarding the cause of the error.
///
/// See also:
///
///  * [ErrorWidget.builder], which can be set to override the default
///    [ErrorWidget] builder.
///  * [FlutterError.reportError], which is typically called with the same
///    [FlutterErrorDetails] object immediately prior to [ErrorWidget.builder]
///    being called.
4272
typedef ErrorWidgetBuilder = Widget Function(FlutterErrorDetails details);
4273

4274 4275
/// A widget that renders an exception's message.
///
4276
/// This widget is used when a build method fails, to help with determining
4277 4278 4279
/// where the problem lies. Exceptions are also logged to the console, which you
/// can read using `flutter logs`. The console will also include additional
/// information such as the stack trace for the exception.
4280 4281 4282
///
/// It is possible to override this widget.
///
4283
/// {@tool sample --template=freeform}
4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321
/// ```dart
/// import 'package:flutter/material.dart';
///
/// void main() {
///   ErrorWidget.builder = (FlutterErrorDetails details) {
///     bool inDebug = false;
///     assert(() { inDebug = true; return true; }());
///     // In debug mode, use the normal error widget which shows
///     // the error message:
///     if (inDebug)
///       return ErrorWidget(details.exception);
///     // In release builds, show a yellow-on-blue message instead:
///     return Container(
///       alignment: Alignment.center,
///       child: Text(
///         'Error!',
///         style: TextStyle(color: Colors.yellow),
///         textDirection: TextDirection.ltr,
///       ),
///     );
///   };
///   // Here we would normally runApp() the root widget, but to demonstrate
///   // the error handling we artificially fail:
///   return runApp(Builder(
///     builder: (BuildContext context) {
///       throw 'oh no, an error';
///     },
///   ));
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [FlutterError.onError], which can be set to a method that exits the
///    application if that is preferable to showing an error message.
///  * <https://flutter.dev/docs/testing/errors>, more information about error
///    handling in Flutter.
4322
class ErrorWidget extends LeafRenderObjectWidget {
4323 4324 4325 4326 4327 4328 4329 4330 4331
  /// Creates a widget that displays the given exception.
  ///
  /// The message will be the stringification of the given exception, unless
  /// computing that value itself throws an exception, in which case it will
  /// be the string "Error".
  ///
  /// If this object is inspected from an IDE or the devtools, and the original
  /// exception is a [FlutterError] object, the original exception itself will
  /// be shown in the inspection output.
4332 4333
  ErrorWidget(Object exception)
    : message = _stringify(exception),
4334
      _flutterError = exception is FlutterError ? exception : null,
4335
      super(key: UniqueKey());
4336

4337 4338 4339 4340 4341 4342 4343 4344
  /// Creates a widget that displays the given error message.
  ///
  /// An explicit [FlutterError] can be provided to be reported to inspection
  /// tools. It need not match the message.
  ErrorWidget.withDetails({ this.message = '', FlutterError error })
    : _flutterError = error,
      super(key: UniqueKey());

4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362
  /// The configurable factory for [ErrorWidget].
  ///
  /// When an error occurs while building a widget, the broken widget is
  /// replaced by the widget returned by this function. By default, an
  /// [ErrorWidget] is returned.
  ///
  /// The system is typically in an unstable state when this function is called.
  /// An exception has just been thrown in the middle of build (and possibly
  /// layout), so surrounding widgets and render objects may be in a rather
  /// fragile state. The framework itself (especially the [BuildOwner]) may also
  /// be confused, and additional exceptions are quite likely to be thrown.
  ///
  /// Because of this, it is highly recommended that the widget returned from
  /// this function perform the least amount of work possible. A
  /// [LeafRenderObjectWidget] is the best choice, especially one that
  /// corresponds to a [RenderBox] that can handle the most absurd of incoming
  /// constraints. The default constructor maps to a [RenderErrorBox].
  ///
4363 4364 4365
  /// The default behavior is to show the exception's message in debug mode,
  /// and to show nothing but a gray background in release builds.
  ///
4366 4367 4368 4369 4370 4371
  /// See also:
  ///
  ///  * [FlutterError.onError], which is typically called with the same
  ///    [FlutterErrorDetails] object immediately prior to this callback being
  ///    invoked, and which can also be configured to control how errors are
  ///    reported.
4372 4373 4374
  ///  * <https://flutter.dev/docs/testing/errors>, more information about error
  ///    handling in Flutter.
  static ErrorWidgetBuilder builder = _defaultErrorWidgetBuilder;
4375

4376 4377 4378 4379 4380 4381 4382 4383 4384
  static Widget _defaultErrorWidgetBuilder(FlutterErrorDetails details) {
    String message = '';
    assert(() {
      message = _stringify(details.exception) + '\nSee also: https://flutter.dev/docs/testing/errors';
      return true;
    }());
    final Object exception = details.exception;
    return ErrorWidget.withDetails(message: message, error: exception is FlutterError ? exception : null);
  }
4385 4386 4387 4388

  static String _stringify(Object exception) {
    try {
      return exception.toString();
4389 4390 4391
    } catch (e) {
      // intentionally left empty.
    }
4392
    return 'Error';
4393 4394
  }

4395 4396 4397 4398
  /// The message to display.
  final String message;
  final FlutterError _flutterError;

4399
  @override
4400
  RenderBox createRenderObject(BuildContext context) => RenderErrorBox(message);
4401

4402
  @override
4403 4404
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
4405 4406 4407 4408
    if (_flutterError == null)
      properties.add(StringProperty('message', message, quoted: false));
    else
      properties.add(_flutterError.toDiagnosticsNode(style: DiagnosticsTreeStyle.whitespace));
4409
  }
4410 4411
}

4412 4413 4414 4415
/// Signature for a function that creates a widget, e.g. [StatelessWidget.build]
/// or [State.build].
///
/// Used by [Builder.builder], [OverlayEntry.builder], etc.
4416 4417 4418 4419 4420 4421
///
/// See also:
///
///  * [IndexedWidgetBuilder], which is similar but also takes an index.
///  * [TransitionBuilder], which is similar but also takes a child.
///  * [ValueWidgetBuilder], which is similar but takes a value and a child.
4422
typedef WidgetBuilder = Widget Function(BuildContext context);
4423

4424 4425 4426
/// Signature for a function that creates a widget for a given index, e.g., in a
/// list.
///
4427
/// Used by [ListView.builder] and other APIs that use lazily-generated widgets.
4428 4429 4430 4431 4432
///
/// See also:
///
///  * [WidgetBuilder], which is similar but only takes a [BuildContext].
///  * [TransitionBuilder], which is similar but also takes a child.
4433
typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
4434

4435 4436 4437 4438 4439 4440
/// A builder that builds a widget given a child.
///
/// The child should typically be part of the returned widget tree.
///
/// Used by [AnimatedBuilder.builder], as well as [WidgetsApp.builder] and
/// [MaterialApp.builder].
4441 4442 4443 4444 4445 4446
///
/// See also:
///
///  * [WidgetBuilder], which is similar but only takes a [BuildContext].
///  * [IndexedWidgetBuilder], which is similar but also takes an index.
///  * [ValueWidgetBuilder], which is similar but takes a value and a child.
4447
typedef TransitionBuilder = Widget Function(BuildContext context, Widget child);
4448

4449 4450
/// A builder that creates a widget given the two callbacks `onStepContinue` and
/// `onStepCancel`.
4451 4452
///
/// Used by [Stepper.builder].
4453 4454 4455 4456
///
/// See also:
///
///  * [WidgetBuilder], which is similar but only takes a [BuildContext].
4457
typedef ControlsWidgetBuilder = Widget Function(BuildContext context, { VoidCallback onStepContinue, VoidCallback onStepCancel });
4458

4459 4460 4461 4462
/// An [Element] that composes other [Element]s.
///
/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
/// [RenderObject]s indirectly by creating other [Element]s.
4463 4464
///
/// Contrast with [RenderObjectElement].
4465
abstract class ComponentElement extends Element {
4466
  /// Creates an element that uses the given widget as its configuration.
4467
  ComponentElement(Widget widget) : super(widget);
4468 4469 4470

  Element _child;

4471 4472 4473 4474
  bool _debugDoingBuild = false;
  @override
  bool get debugDoingBuild => _debugDoingBuild;

4475
  @override
4476 4477 4478 4479
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    assert(_child == null);
    assert(_active);
Ian Hickson's avatar
Ian Hickson committed
4480
    _firstBuild();
4481 4482 4483
    assert(_child != null);
  }

Ian Hickson's avatar
Ian Hickson committed
4484 4485 4486 4487
  void _firstBuild() {
    rebuild();
  }

4488 4489 4490
  /// Calls the [StatelessWidget.build] method of the [StatelessWidget] object
  /// (for stateless widgets) or the [State.build] method of the [State] object
  /// (for stateful widgets) and then updates the widget tree.
4491
  ///
4492 4493
  /// Called automatically during [mount] to generate the first build, and by
  /// [rebuild] when the element needs updating.
4494
  @override
4495
  void performRebuild() {
4496 4497
    if (!kReleaseMode && debugProfileBuildsEnabled)
      Timeline.startSync('${widget.runtimeType}',  arguments: timelineWhitelistArguments);
4498

4499 4500 4501
    assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
    Widget built;
    try {
4502 4503 4504 4505
      assert(() {
        _debugDoingBuild = true;
        return true;
      }());
4506
      built = build();
4507 4508 4509 4510
      assert(() {
        _debugDoingBuild = false;
        return true;
      }());
4511
      debugWidgetBuilderValue(widget, built);
4512
    } catch (e, stack) {
4513
      _debugDoingBuild = false;
4514 4515 4516 4517 4518 4519 4520 4521
      built = ErrorWidget.builder(
        _debugReportException(
          ErrorDescription('building $this'),
          e,
          stack,
          informationCollector: () sync* {
            yield DiagnosticsDebugCreator(DebugCreator(this));
          },
4522
        ),
4523
      );
4524
    } finally {
4525
      // We delay marking the element as clean until after calling build() so
4526 4527 4528 4529 4530 4531 4532 4533
      // that attempts to markNeedsBuild() during build() will be ignored.
      _dirty = false;
      assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false));
    }
    try {
      _child = updateChild(_child, built, slot);
      assert(_child != null);
    } catch (e, stack) {
4534 4535 4536 4537 4538 4539 4540 4541
      built = ErrorWidget.builder(
        _debugReportException(
          ErrorDescription('building $this'),
          e,
          stack,
          informationCollector: () sync* {
            yield DiagnosticsDebugCreator(DebugCreator(this));
          },
4542
        ),
4543
      );
4544 4545
      _child = updateChild(null, built, slot);
    }
4546

4547 4548
    if (!kReleaseMode && debugProfileBuildsEnabled)
      Timeline.finishSync();
4549 4550
  }

4551 4552 4553
  /// Subclasses should override this function to actually call the appropriate
  /// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
  /// their widget.
4554 4555 4556
  @protected
  Widget build();

4557
  @override
4558 4559 4560 4561 4562
  void visitChildren(ElementVisitor visitor) {
    if (_child != null)
      visitor(_child);
  }

4563
  @override
4564
  void forgetChild(Element child) {
4565 4566
    assert(child == _child);
    _child = null;
4567
    super.forgetChild(child);
4568 4569 4570
  }
}

4571
/// An [Element] that uses a [StatelessWidget] as its configuration.
4572
class StatelessElement extends ComponentElement {
4573
  /// Creates an element that uses the given widget as its configuration.
4574
  StatelessElement(StatelessWidget widget) : super(widget);
4575

4576
  @override
4577
  StatelessWidget get widget => super.widget as StatelessWidget;
4578

4579 4580 4581
  @override
  Widget build() => widget.build(this);

4582
  @override
4583
  void update(StatelessWidget newWidget) {
4584 4585 4586 4587 4588 4589
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}
4590

4591
/// An [Element] that uses a [StatefulWidget] as its configuration.
4592
class StatefulElement extends ComponentElement {
4593
  /// Creates an element that uses the given widget as its configuration.
4594
  StatefulElement(StatefulWidget widget)
4595 4596
      : _state = widget.createState(),
        super(widget) {
4597 4598
    assert(() {
      if (!_state._debugTypesAreRight(widget)) {
4599 4600 4601 4602 4603 4604
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>'),
          ErrorDescription(
            'The createState function for ${widget.runtimeType} returned a state '
            'of type ${_state.runtimeType}, which is not a subtype of '
            'State<${widget.runtimeType}>, violating the contract for createState.'
4605
          ),
4606
        ]);
4607 4608
      }
      return true;
4609
    }());
4610 4611
    assert(_state._element == null);
    _state._element = this;
4612 4613 4614 4615 4616 4617
    assert(
      _state._widget == null,
      'The createState function for $widget returned an old or invalid state '
      'instance: ${_state._widget}, which is not null, violating the contract '
      'for createState.',
    );
4618
    _state._widget = widget;
4619
    assert(_state._debugLifecycleState == _StateLifecycle.created);
Ian Hickson's avatar
Ian Hickson committed
4620 4621
  }

4622
  @override
Dan Field's avatar
Dan Field committed
4623
  Widget build() => _state.build(this);
4624

4625 4626 4627 4628 4629
  /// The [State] instance associated with this location in the tree.
  ///
  /// There is a one-to-one relationship between [State] objects and the
  /// [StatefulElement] objects that hold them. The [State] objects are created
  /// by [StatefulElement] in [mount].
4630 4631
  State<StatefulWidget> get state => _state;
  State<StatefulWidget> _state;
Ian Hickson's avatar
Ian Hickson committed
4632

4633
  @override
4634
  void reassemble() {
4635
    state.reassemble();
4636
    super.reassemble();
4637 4638
  }

4639
  @override
Ian Hickson's avatar
Ian Hickson committed
4640 4641
  void _firstBuild() {
    assert(_state._debugLifecycleState == _StateLifecycle.created);
4642
    try {
4643
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
4644 4645 4646
      final dynamic debugCheckForReturnedFuture = _state.initState() as dynamic;
      assert(() {
        if (debugCheckForReturnedFuture is Future) {
4647 4648 4649 4650 4651 4652
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('${_state.runtimeType}.initState() returned a Future.'),
            ErrorDescription('State.initState() must be a void method without an `async` keyword.'),
            ErrorHint(
              'Rather than awaiting on asynchronous work directly inside of initState, '
              'call a separate method to do this work without awaiting it.'
4653
            ),
4654
          ]);
4655 4656 4657
        }
        return true;
      }());
4658
    } finally {
4659
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
4660
    }
4661 4662 4663 4664
    assert(() {
      _state._debugLifecycleState = _StateLifecycle.initialized;
      return true;
    }());
4665
    _state.didChangeDependencies();
4666 4667 4668 4669
    assert(() {
      _state._debugLifecycleState = _StateLifecycle.ready;
      return true;
    }());
Ian Hickson's avatar
Ian Hickson committed
4670
    super._firstBuild();
4671
  }
4672

Dan Field's avatar
Dan Field committed
4673 4674 4675 4676 4677 4678 4679 4680 4681
  @override
  void performRebuild() {
    if (_didChangeDependencies) {
      _state.didChangeDependencies();
      _didChangeDependencies = false;
    }
    super.performRebuild();
  }

4682
  @override
4683
  void update(StatefulWidget newWidget) {
4684 4685
    super.update(newWidget);
    assert(widget == newWidget);
4686 4687 4688
    final StatefulWidget oldWidget = _state._widget;
    // Notice that we mark ourselves as dirty before calling didUpdateWidget to
    // let authors call setState from within didUpdateWidget without triggering
4689 4690
    // asserts.
    _dirty = true;
4691
    _state._widget = widget as StatefulWidget;
4692 4693
    try {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
4694 4695 4696
      final dynamic debugCheckForReturnedFuture = _state.didUpdateWidget(oldWidget) as dynamic;
      assert(() {
        if (debugCheckForReturnedFuture is Future) {
4697 4698 4699 4700 4701 4702
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('${_state.runtimeType}.didUpdateWidget() returned a Future.'),
            ErrorDescription( 'State.didUpdateWidget() must be a void method without an `async` keyword.'),
            ErrorHint(
              'Rather than awaiting on asynchronous work directly inside of didUpdateWidget, '
              'call a separate method to do this work without awaiting it.'
4703
            ),
4704
          ]);
4705 4706 4707
        }
        return true;
      }());
4708 4709
    } finally {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
4710
    }
4711
    rebuild();
4712
  }
4713

4714 4715 4716
  @override
  void activate() {
    super.activate();
4717
    // Since the State could have observed the deactivate() and thus disposed of
4718
    // resources allocated in the build method, we have to rebuild the widget
4719 4720
    // so that its State can reallocate its resources.
    assert(_active); // otherwise markNeedsBuild is a no-op
4721 4722 4723
    markNeedsBuild();
  }

4724
  @override
4725 4726 4727 4728 4729
  void deactivate() {
    _state.deactivate();
    super.deactivate();
  }

4730
  @override
4731 4732 4733 4734 4735 4736
  void unmount() {
    super.unmount();
    _state.dispose();
    assert(() {
      if (_state._debugLifecycleState == _StateLifecycle.defunct)
        return true;
4737 4738 4739 4740 4741
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('${_state.runtimeType}.dispose failed to call super.dispose.'),
        ErrorDescription(
          'dispose() implementations must always call their superclass dispose() method, to ensure '
         'that all the resources used by the widget are fully released.'
4742
        ),
4743
      ]);
4744
    }());
4745 4746 4747
    _state._element = null;
    _state = null;
  }
4748

4749 4750 4751 4752 4753
  // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189
  @Deprecated(
    'Use dependOnInheritedElement instead. '
    'This feature was deprecated after v1.12.1.'
  )
4754
  @override
4755
  InheritedWidget inheritFromElement(Element ancestor, { Object aspect }) {
4756 4757 4758 4759 4760
    return dependOnInheritedElement(ancestor, aspect: aspect);
  }

  @override
  InheritedWidget dependOnInheritedElement(Element ancestor, { Object aspect }) {
4761
    assert(ancestor != null);
4762
    assert(() {
4763
      final Type targetType = ancestor.widget.runtimeType;
4764
      if (state._debugLifecycleState == _StateLifecycle.created) {
4765
        throw FlutterError.fromParts(<DiagnosticsNode>[
4766
          ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called before ${_state.runtimeType}.initState() completed.'),
4767 4768
          ErrorDescription(
            'When an inherited widget changes, for example if the value of Theme.of() changes, '
4769
            "its dependent widgets are rebuilt. If the dependent widget's reference to "
4770 4771 4772 4773 4774 4775 4776 4777
            'the inherited widget is in a constructor or an initState() method, '
            'then the rebuilt dependent widget will not reflect the changes in the '
            'inherited widget.',
          ),
          ErrorHint(
            'Typically references to inherited widgets should occur in widget build() methods. Alternatively, '
            'initialization based on inherited widgets can be placed in the didChangeDependencies method, which '
            'is called after initState and whenever the dependencies change thereafter.'
4778
          ),
4779
        ]);
4780 4781
      }
      if (state._debugLifecycleState == _StateLifecycle.defunct) {
4782
        throw FlutterError.fromParts(<DiagnosticsNode>[
4783
          ErrorSummary('dependOnInheritedWidgetOfExactType<$targetType>() or dependOnInheritedElement() was called after dispose(): $this'),
4784
          ErrorDescription(
4785
            'This error happens if you call dependOnInheritedWidgetOfExactType() on the '
4786 4787 4788
            'BuildContext for a widget that no longer appears in the widget tree '
            '(e.g., whose parent widget no longer includes the widget in its '
            'build). This error can occur when code calls '
4789
            'dependOnInheritedWidgetOfExactType() from a timer or an animation callback.'
4790 4791 4792 4793 4794
          ),
          ErrorHint(
            'The preferred solution is to cancel the timer or stop listening to the '
            'animation in the dispose() callback. Another solution is to check the '
            '"mounted" property of this object before calling '
4795
            'dependOnInheritedWidgetOfExactType() to ensure the object is still in the '
4796 4797 4798 4799
            'tree.'
          ),
          ErrorHint(
            'This error might indicate a memory leak if '
4800
            'dependOnInheritedWidgetOfExactType() is being called because another object '
4801 4802 4803 4804 4805
            'is retaining a reference to this State object after it has been '
            'removed from the tree. To avoid memory leaks, consider breaking the '
            'reference to this object during dispose().'
          ),
        ]);
4806 4807
      }
      return true;
4808
    }());
4809
    return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
4810 4811
  }

4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822
  /// This controls whether we should call [State.didChangeDependencies] from
  /// the start of [build], to avoid calls when the [State] will not get built.
  /// This can happen when the widget has dropped out of the tree, but depends
  /// on an [InheritedWidget] that is still in the tree.
  ///
  /// It is set initially to false, since [_firstBuild] makes the initial call
  /// on the [state]. When it is true, [build] will call
  /// `state.didChangeDependencies` and then sets it to false. Subsequent calls
  /// to [didChangeDependencies] set it to true.
  bool _didChangeDependencies = false;

4823
  @override
4824 4825
  void didChangeDependencies() {
    super.didChangeDependencies();
4826
    _didChangeDependencies = true;
4827 4828
  }

4829 4830 4831 4832 4833 4834 4835 4836 4837 4838
  @override
  DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style }) {
    return _ElementDiagnosticableTreeNode(
      name: name,
      value: this,
      style: style,
      stateful: true,
    );
  }

4839
  @override
4840 4841
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
4842
    properties.add(DiagnosticsProperty<State<StatefulWidget>>('state', state, defaultValue: null));
4843
  }
4844 4845
}

4846
/// An [Element] that uses a [ProxyWidget] as its configuration.
4847
abstract class ProxyElement extends ComponentElement {
4848
  /// Initializes fields for subclasses.
4849
  ProxyElement(ProxyWidget widget) : super(widget);
Hixie's avatar
Hixie committed
4850

4851
  @override
4852
  ProxyWidget get widget => super.widget as ProxyWidget;
4853

4854
  @override
4855
  Widget build() => widget.child;
4856

4857
  @override
4858
  void update(ProxyWidget newWidget) {
4859
    final ProxyWidget oldWidget = widget;
Hixie's avatar
Hixie committed
4860 4861 4862 4863
    assert(widget != null);
    assert(widget != newWidget);
    super.update(newWidget);
    assert(widget == newWidget);
4864
    updated(oldWidget);
Hixie's avatar
Hixie committed
4865 4866 4867 4868
    _dirty = true;
    rebuild();
  }

4869
  /// Called during build when the [widget] has changed.
4870
  ///
4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883
  /// By default, calls [notifyClients]. Subclasses may override this method to
  /// avoid calling [notifyClients] unnecessarily (e.g. if the old and new
  /// widgets are equivalent).
  @protected
  void updated(covariant ProxyWidget oldWidget) {
    notifyClients(oldWidget);
  }

  /// Notify other objects that the widget associated with this element has
  /// changed.
  ///
  /// Called during [update] (via [updated]) after changing the widget
  /// associated with this element but before rebuilding this element.
4884
  @protected
4885
  void notifyClients(covariant ProxyWidget oldWidget);
Hixie's avatar
Hixie committed
4886 4887
}

4888
/// An [Element] that uses a [ParentDataWidget] as its configuration.
4889
class ParentDataElement<T extends ParentData> extends ProxyElement {
4890
  /// Creates an element that uses the given widget as its configuration.
4891 4892
  ParentDataElement(ParentDataWidget<T> widget) : super(widget);

4893
  @override
4894
  ParentDataWidget<T> get widget => super.widget as ParentDataWidget<T>;
4895

4896 4897 4898 4899 4900
  void _applyParentData(ParentDataWidget<T> widget) {
    void applyParentDataToChild(Element child) {
      if (child is RenderObjectElement) {
        child._updateParentData(widget);
      } else {
4901
        assert(child is! ParentDataElement<ParentData>);
4902 4903
        child.visitChildren(applyParentDataToChild);
      }
4904
    }
4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921
    visitChildren(applyParentDataToChild);
  }

  /// Calls [ParentDataWidget.applyParentData] on the given widget, passing it
  /// the [RenderObject] whose parent data this element is ultimately
  /// responsible for.
  ///
  /// This allows a render object's [RenderObject.parentData] to be modified
  /// without triggering a build. This is generally ill-advised, but makes sense
  /// in situations such as the following:
  ///
  ///  * Build and layout are currently under way, but the [ParentData] in question
  ///    does not affect layout, and the value to be applied could not be
  ///    determined before build and layout (e.g. it depends on the layout of a
  ///    descendant).
  ///
  ///  * Paint is currently under way, but the [ParentData] in question does not
4922
  ///    affect layout or paint, and the value to be applied could not be
4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944
  ///    determined before paint (e.g. it depends on the compositing phase).
  ///
  /// In either case, the next build is expected to cause this element to be
  /// configured with the given new widget (or a widget with equivalent data).
  ///
  /// Only [ParentDataWidget]s that return true for
  /// [ParentDataWidget.debugCanApplyOutOfTurn] can be applied this way.
  ///
  /// The new widget must have the same child as the current widget.
  ///
  /// An example of when this is used is the [AutomaticKeepAlive] widget. If it
  /// receives a notification during the build of one of its descendants saying
  /// that its child must be kept alive, it will apply a [KeepAlive] widget out
  /// of turn. This is safe, because by definition the child is already alive,
  /// and therefore this will not change the behavior of the parent this frame.
  /// It is more efficient than requesting an additional frame just for the
  /// purpose of updating the [KeepAlive] widget.
  void applyWidgetOutOfTurn(ParentDataWidget<T> newWidget) {
    assert(newWidget != null);
    assert(newWidget.debugCanApplyOutOfTurn());
    assert(newWidget.child == widget.child);
    _applyParentData(newWidget);
4945 4946
  }

4947
  @override
4948
  void notifyClients(ParentDataWidget<T> oldWidget) {
4949
    _applyParentData(widget);
4950 4951
  }
}
4952

4953
/// An [Element] that uses an [InheritedWidget] as its configuration.
4954
class InheritedElement extends ProxyElement {
4955
  /// Creates an element that uses the given widget as its configuration.
Hixie's avatar
Hixie committed
4956 4957
  InheritedElement(InheritedWidget widget) : super(widget);

4958
  @override
4959
  InheritedWidget get widget => super.widget as InheritedWidget;
4960

4961
  final Map<Element, Object> _dependents = HashMap<Element, Object>();
4962

4963
  @override
4964
  void _updateInheritance() {
4965
    assert(_active);
4966 4967
    final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
    if (incomingWidgets != null)
4968
      _inheritedWidgets = HashMap<Type, InheritedElement>.from(incomingWidgets);
4969
    else
4970
      _inheritedWidgets = HashMap<Type, InheritedElement>();
4971 4972
    _inheritedWidgets[widget.runtimeType] = this;
  }
4973

4974
  @override
4975 4976
  void debugDeactivated() {
    assert(() {
4977
      assert(_dependents.isEmpty);
4978
      return true;
4979
    }());
4980 4981 4982
    super.debugDeactivated();
  }

4983 4984 4985 4986 4987 4988 4989 4990 4991 4992
  /// Returns the dependencies value recorded for [dependent]
  /// with [setDependencies].
  ///
  /// Each dependent element is mapped to a single object value
  /// which represents how the element depends on this
  /// [InheritedElement]. This value is null by default and by default
  /// dependent elements are rebuilt unconditionally.
  ///
  /// Subclasses can manage these values with [updateDependencies]
  /// so that they can selectively rebuild dependents in
4993
  /// [notifyDependent].
4994 4995 4996 4997 4998 4999
  ///
  /// This method is typically only called in overrides of [updateDependencies].
  ///
  /// See also:
  ///
  ///  * [updateDependencies], which is called each time a dependency is
5000
  ///    created with [dependOnInheritedWidgetOfExactType].
5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019
  ///  * [setDependencies], which sets dependencies value for a dependent
  ///    element.
  ///  * [notifyDependent], which can be overridden to use a dependent's
  ///    dependencies value to decide if the dependent needs to be rebuilt.
  ///  * [InheritedModel], which is an example of a class that uses this method
  ///    to manage dependency values.
  @protected
  Object getDependencies(Element dependent) {
    return _dependents[dependent];
  }

  /// Sets the value returned by [getDependencies] value for [dependent].
  ///
  /// Each dependent element is mapped to a single object value
  /// which represents how the element depends on this
  /// [InheritedElement]. The [updateDependencies] method sets this value to
  /// null by default so that dependent elements are rebuilt unconditionally.
  ///
  /// Subclasses can manage these values with [updateDependencies]
5020
  /// so that they can selectively rebuild dependents in [notifyDependent].
5021 5022 5023 5024 5025 5026
  ///
  /// This method is typically only called in overrides of [updateDependencies].
  ///
  /// See also:
  ///
  ///  * [updateDependencies], which is called each time a dependency is
5027
  ///    created with [dependOnInheritedWidgetOfExactType].
5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038
  ///  * [getDependencies], which returns the current value for a dependent
  ///    element.
  ///  * [notifyDependent], which can be overridden to use a dependent's
  ///    [getDependencies] value to decide if the dependent needs to be rebuilt.
  ///  * [InheritedModel], which is an example of a class that uses this method
  ///    to manage dependency values.
  @protected
  void setDependencies(Element dependent, Object value) {
    _dependents[dependent] = value;
  }

5039
  /// Called by [dependOnInheritedWidgetOfExactType] when a new [dependent] is added.
5040 5041 5042 5043 5044 5045 5046 5047 5048 5049
  ///
  /// Each dependent element can be mapped to a single object value with
  /// [setDependencies]. This method can lookup the existing dependencies with
  /// [getDependencies].
  ///
  /// By default this method sets the inherited dependencies for [dependent]
  /// to null. This only serves to record an unconditional dependency on
  /// [dependent].
  ///
  /// Subclasses can manage their own dependencies values so that they
5050
  /// can selectively rebuild dependents in [notifyDependent].
5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075
  ///
  /// See also:
  ///
  ///  * [getDependencies], which returns the current value for a dependent
  ///    element.
  ///  * [setDependencies], which sets the value for a dependent element.
  ///  * [notifyDependent], which can be overridden to use a dependent's
  ///    dependencies value to decide if the dependent needs to be rebuilt.
  ///  * [InheritedModel], which is an example of a class that uses this method
  ///    to manage dependency values.
  @protected
  void updateDependencies(Element dependent, Object aspect) {
    setDependencies(dependent, null);
  }

  /// Called by [notifyClients] for each dependent.
  ///
  /// Calls `dependent.didChangeDependencies()` by default.
  ///
  /// Subclasses can override this method to selectively call
  /// [didChangeDependencies] based on the value of [getDependencies].
  ///
  /// See also:
  ///
  ///  * [updateDependencies], which is called each time a dependency is
5076
  ///    created with [dependOnInheritedWidgetOfExactType].
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086
  ///  * [getDependencies], which returns the current value for a dependent
  ///    element.
  ///  * [setDependencies], which sets the value for a dependent element.
  ///  * [InheritedModel], which is an example of a class that uses this method
  ///    to manage dependency values.
  @protected
  void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
    dependent.didChangeDependencies();
  }

5087 5088 5089
  /// Calls [Element.didChangeDependencies] of all dependent elements, if
  /// [InheritedWidget.updateShouldNotify] returns true.
  ///
5090
  /// Called by [update], immediately prior to [build].
5091
  ///
5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104
  /// Calls [notifyClients] to actually trigger the notifications.
  @override
  void updated(InheritedWidget oldWidget) {
    if (widget.updateShouldNotify(oldWidget))
      super.updated(oldWidget);
  }

  /// Notifies all dependent elements that this inherited widget has changed, by
  /// calling [Element.didChangeDependencies].
  ///
  /// This method must only be called during the build phase. Usually this
  /// method is called automatically when an inherited widget is rebuilt, e.g.
  /// as a result of calling [State.setState] above the inherited widget.
5105
  ///
5106 5107 5108 5109
  /// See also:
  ///
  ///  * [InheritedNotifier], a subclass of [InheritedWidget] that also calls
  ///    this method when its [Listenable] sends a notification.
5110
  @override
5111
  void notifyClients(InheritedWidget oldWidget) {
5112
    assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
5113
    for (final Element dependent in _dependents.keys) {
5114 5115
      assert(() {
        // check that it really is our descendant
5116
        Element ancestor = dependent._parent;
5117 5118 5119
        while (ancestor != this && ancestor != null)
          ancestor = ancestor._parent;
        return ancestor == this;
5120
      }());
5121
      // check that it really depends on us
5122
      assert(dependent._dependencies.contains(this));
5123
      notifyDependent(oldWidget, dependent);
5124 5125
    }
  }
5126
}
5127

5128
/// An [Element] that uses a [RenderObjectWidget] as its configuration.
5129 5130 5131 5132 5133 5134
///
/// [RenderObjectElement] objects have an associated [RenderObject] widget in
/// the render tree, which handles concrete operations like laying out,
/// painting, and hit testing.
///
/// Contrast with [ComponentElement].
5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170
///
/// For details on the lifecycle of an element, see the discussion at [Element].
///
/// ## Writing a RenderObjectElement subclass
///
/// There are three common child models used by most [RenderObject]s:
///
/// * Leaf render objects, with no children: The [LeafRenderObjectElement] class
///   handles this case.
///
/// * A single child: The [SingleChildRenderObjectElement] class handles this
///   case.
///
/// * A linked list of children: The [MultiChildRenderObjectElement] class
///   handles this case.
///
/// Sometimes, however, a render object's child model is more complicated. Maybe
/// it has a two-dimensional array of children. Maybe it constructs children on
/// demand. Maybe it features multiple lists. In such situations, the
/// corresponding [Element] for the [Widget] that configures that [RenderObject]
/// will be a new subclass of [RenderObjectElement].
///
/// Such a subclass is responsible for managing children, specifically the
/// [Element] children of this object, and the [RenderObject] children of its
/// corresponding [RenderObject].
///
/// ### Specializing the getters
///
/// [RenderObjectElement] objects spend much of their time acting as
/// intermediaries between their [widget] and their [renderObject]. To make this
/// more tractable, most [RenderObjectElement] subclasses override these getters
/// so that they return the specific type that the element expects, e.g.:
///
/// ```dart
/// class FooElement extends RenderObjectElement {
///
5171 5172
///   @override
///   Foo get widget => super.widget;
5173
///
5174 5175
///   @override
///   RenderFoo get renderObject => super.renderObject;
5176
///
5177
///   // ...
5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201
/// }
/// ```
///
/// ### Slots
///
/// Each child [Element] corresponds to a [RenderObject] which should be
/// attached to this element's render object as a child.
///
/// However, the immediate children of the element may not be the ones that
/// eventually produce the actual [RenderObject] that they correspond to. For
/// example a [StatelessElement] (the element of a [StatelessWidget]) simply
/// corresponds to whatever [RenderObject] its child (the element returned by
/// its [StatelessWidget.build] method) corresponds to.
///
/// Each child is therefore assigned a _slot_ token. This is an identifier whose
/// meaning is private to this [RenderObjectElement] node. When the descendant
/// that finally produces the [RenderObject] is ready to attach it to this
/// node's render object, it passes that slot token back to this node, and that
/// allows this node to cheaply identify where to put the child render object
/// relative to the others in the parent render object.
///
/// ### Updating children
///
/// Early in the lifecycle of an element, the framework calls the [mount]
5202
/// method. This method should call [updateChild] for each child, passing in
5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220
/// the widget for that child, and the slot for that child, thus obtaining a
/// list of child [Element]s.
///
/// Subsequently, the framework will call the [update] method. In this method,
/// the [RenderObjectElement] should call [updateChild] for each child, passing
/// in the [Element] that was obtained during [mount] or the last time [update]
/// was run (whichever happened most recently), the new [Widget], and the slot.
/// This provides the object with a new list of [Element] objects.
///
/// Where possible, the [update] method should attempt to map the elements from
/// the last pass to the widgets in the new pass. For example, if one of the
/// elements from the last pass was configured with a particular [Key], and one
/// of the widgets in this new pass has that same key, they should be paired up,
/// and the old element should be updated with the widget (and the slot
/// corresponding to the new widget's new position, also). The [updateChildren]
/// method may be useful in this regard.
///
/// [updateChild] should be called for children in their logical order. The
5221
/// order can matter; for example, if two of the children use [PageStorage]'s
Ian Hickson's avatar
Ian Hickson committed
5222 5223
/// `writeState` feature in their build method (and neither has a [Widget.key]),
/// then the state written by the first will be overwritten by the second.
5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236
///
/// #### Dynamically determining the children during the build phase
///
/// The child widgets need not necessarily come from this element's widget
/// verbatim. They could be generated dynamically from a callback, or generated
/// in other more creative ways.
///
/// #### Dynamically determining the children during layout
///
/// If the widgets are to be generated at layout time, then generating them when
/// the [update] method won't work: layout of this element's render object
/// hasn't started yet at that point. Instead, the [update] method can mark the
/// render object as needing layout (see [RenderObject.markNeedsLayout]), and
Ian Hickson's avatar
Ian Hickson committed
5237
/// then the render object's [RenderObject.performLayout] method can call back
5238 5239
/// to the element to have it generate the widgets and call [updateChild]
/// accordingly.
5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263
///
/// For a render object to call an element during layout, it must use
/// [RenderObject.invokeLayoutCallback]. For an element to call [updateChild]
/// outside of its [update] method, it must use [BuildOwner.buildScope].
///
/// The framework provides many more checks in normal operation than it does
/// when doing a build during layout. For this reason, creating widgets with
/// layout-time build semantics should be done with great care.
///
/// #### Handling errors when building
///
/// If an element calls a builder function to obtain widgets for its children,
/// it may find that the build throws an exception. Such exceptions should be
/// caught and reported using [FlutterError.reportError]. If a child is needed
/// but a builder has failed in this way, an instance of [ErrorWidget] can be
/// used instead.
///
/// ### Detaching children
///
/// It is possible, when using [GlobalKey]s, for a child to be proactively
/// removed by another element before this element has been updated.
/// (Specifically, this happens when the subtree rooted at a widget with a
/// particular [GlobalKey] is being moved from this element to an element
/// processed earlier in the build phase.) When this happens, this element's
5264
/// [forgetChild] method will be called with a reference to the affected child
5265 5266
/// element.
///
5267
/// The [forgetChild] method of a [RenderObjectElement] subclass must remove the
5268 5269 5270 5271
/// child element from its child list, so that when it next [update]s its
/// children, the removed child is not considered.
///
/// For performance reasons, if there are many elements, it may be quicker to
5272
/// track which elements were forgotten by storing them in a [Set], rather than
5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286
/// proactively mutating the local record of the child list and the identities
/// of all the slots. For example, see the implementation of
/// [MultiChildRenderObjectElement].
///
/// ### Maintaining the render object tree
///
/// Once a descendant produces a render object, it will call
/// [insertChildRenderObject]. If the descendant's slot changes identity, it
/// will call [moveChildRenderObject]. If a descendant goes away, it will call
/// [removeChildRenderObject].
///
/// These three methods should update the render tree accordingly, attaching,
/// moving, and detaching the given child render object from this element's own
/// render object respectively.
5287 5288 5289 5290 5291 5292 5293
///
/// ### Walking the children
///
/// If a [RenderObjectElement] object has any children [Element]s, it must
/// expose them in its implementation of the [visitChildren] method. This method
/// is used by many of the framework's internal mechanisms, and so should be
/// fast. It is also used by the test framework and [debugDumpApp].
5294
abstract class RenderObjectElement extends Element {
5295
  /// Creates an element that uses the given widget as its configuration.
5296 5297
  RenderObjectElement(RenderObjectWidget widget) : super(widget);

5298
  @override
5299
  RenderObjectWidget get widget => super.widget as RenderObjectWidget;
5300

5301
  /// The underlying [RenderObject] for this element.
5302
  @override
5303
  RenderObject get renderObject => _renderObject;
5304
  RenderObject _renderObject;
5305

5306 5307 5308 5309
  bool _debugDoingBuild = false;
  @override
  bool get debugDoingBuild => _debugDoingBuild;

5310
  RenderObjectElement _ancestorRenderObjectElement;
5311

5312 5313 5314 5315
  RenderObjectElement _findAncestorRenderObjectElement() {
    Element ancestor = _parent;
    while (ancestor != null && ancestor is! RenderObjectElement)
      ancestor = ancestor._parent;
5316
    return ancestor as RenderObjectElement;
5317 5318
  }

5319
  ParentDataElement<ParentData> _findAncestorParentDataElement() {
5320
    Element ancestor = _parent;
5321
    ParentDataElement<ParentData> result;
5322
    while (ancestor != null && ancestor is! RenderObjectElement) {
5323 5324 5325 5326
      if (ancestor is ParentDataElement<ParentData>) {
        result = ancestor as ParentDataElement<ParentData>;
        break;
      }
5327
      ancestor = ancestor._parent;
5328
    }
5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360
    assert(() {
      if (result == null || ancestor == null) {
        return true;
      }
      // Check that no other ParentDataWidgets want to provide parent data.
      final List<ParentDataElement<ParentData>> badAncestors = <ParentDataElement<ParentData>>[];
      ancestor = ancestor._parent;
      while (ancestor != null && ancestor is! RenderObjectElement) {
        if (ancestor is ParentDataElement<ParentData>) {
          badAncestors.add(ancestor as ParentDataElement<ParentData>);
        }
        ancestor = ancestor._parent;
      }
      if (badAncestors.isNotEmpty) {
        badAncestors.insert(0, result);
        try {
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('Incorrect use of ParentDataWidget.'),
            ErrorDescription('The following ParentDataWidgets are providing parent data to the same RenderObject:'),
            for (final ParentDataElement<ParentData> ancestor in badAncestors)
              ErrorDescription('- ${ancestor.widget} (typically placed directly inside a ${ancestor.widget.debugTypicalAncestorWidgetClass} widget)'),
            ErrorDescription('However, a RenderObject can only receive parent data from at most one ParentDataWidget.'),
            ErrorHint('Usually, this indicates that at least one of the offending ParentDataWidgets listed above is not placed directly inside a compatible ancestor widget.'),
            ErrorDescription('The ownership chain for the RenderObject that received the parent data was:\n  ${debugGetCreatorChain(10)}'),
          ]);
        } on FlutterError catch (e) {
          _debugReportException(ErrorSummary('while looking for parent data.'), e, e.stackTrace);
        }
      }
      return true;
    }());
    return result;
5361 5362
  }

5363
  @override
5364 5365
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
5366 5367 5368 5369
    assert(() {
      _debugDoingBuild = true;
      return true;
    }());
5370
    _renderObject = widget.createRenderObject(this);
5371 5372 5373 5374
    assert(() {
      _debugDoingBuild = false;
      return true;
    }());
5375 5376 5377 5378
    assert(() {
      _debugUpdateRenderObjectOwner();
      return true;
    }());
5379
    assert(_slot == newSlot);
5380
    attachRenderObject(newSlot);
5381
    _dirty = false;
5382 5383
  }

5384
  @override
5385
  void update(covariant RenderObjectWidget newWidget) {
5386 5387
    super.update(newWidget);
    assert(widget == newWidget);
5388 5389 5390 5391
    assert(() {
      _debugUpdateRenderObjectOwner();
      return true;
    }());
5392 5393 5394 5395
    assert(() {
      _debugDoingBuild = true;
      return true;
    }());
5396
    widget.updateRenderObject(this, renderObject);
5397 5398 5399 5400
    assert(() {
      _debugDoingBuild = false;
      return true;
    }());
5401 5402 5403
    _dirty = false;
  }

5404
  void _debugUpdateRenderObjectOwner() {
5405
    assert(() {
5406
      _renderObject.debugCreator = DebugCreator(this);
5407
      return true;
5408
    }());
5409 5410
  }

5411
  @override
5412
  void performRebuild() {
5413 5414 5415 5416
    assert(() {
      _debugDoingBuild = true;
      return true;
    }());
5417
    widget.updateRenderObject(this, renderObject);
5418 5419 5420 5421
    assert(() {
      _debugDoingBuild = false;
      return true;
    }());
5422 5423 5424
    _dirty = false;
  }

5425 5426
  /// Updates the children of this element to use new widgets.
  ///
5427 5428 5429
  /// Attempts to update the given old children list using the given new
  /// widgets, removing obsolete elements and introducing new ones as necessary,
  /// and then returns the new child list.
5430 5431 5432
  ///
  /// During this function the `oldChildren` list must not be modified. If the
  /// caller wishes to remove elements from `oldChildren` re-entrantly while
5433
  /// this function is on the stack, the caller can supply a `forgottenChildren`
5434 5435
  /// argument, which can be modified while this function is on the stack.
  /// Whenever this function reads from `oldChildren`, this function first
5436
  /// checks whether the child is in `forgottenChildren`. If it is, the function
5437 5438
  /// acts as if the child was not in `oldChildren`.
  ///
5439
  /// This function is a convenience wrapper around [updateChild], which updates
5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468
  /// each individual child. When calling [updateChild], this function uses an
  /// [IndexedSlot<Element>] as the value for the `newSlot` argument.
  /// [IndexedSlot.index] is set to the index that the currently processed
  /// `child` corresponds to in the `newWidgets` list and [IndexedSlot.value] is
  /// set to the [Element] of the previous widget in that list (or null if it is
  /// the first child).
  ///
  /// When the [slot] value of an [Element] changes, its
  /// associated [renderObject] needs to move to a new position in the child
  /// list of its parents. If that [RenderObject] organizes its children in a
  /// linked list (as is done by the [ContainerRenderObjectMixin]) this can
  /// be implemented by re-inserting the child [RenderObject] into the
  /// list after the [RenderObject] associated with the [Element] provided as
  /// [IndexedSlot.value] in the [slot] object.
  ///
  /// Simply using the previous sibling as a [slot] is not enough, though, because
  /// child [RenderObject]s are only moved around when the [slot] of their
  /// associated [RenderObjectElement]s is updated. When the order of child
  /// [Element]s is changed, some elements in the list may move to a new index
  /// but still have the same previous sibling. For example, when
  /// `[e1, e2, e3, e4]` is changed to `[e1, e3, e4, e2]` the element e4
  /// continues to have e3 as a previous sibling even though its index in the list
  /// has changed and its [RenderObject] needs to move to come before e2's
  /// [RenderObject]. In order to trigger this move, a new [slot] value needs to
  /// be assigned to its [Element] whenever its index in its
  /// parent's child list changes. Using an [IndexedSlot<Element>] achieves
  /// exactly that and also ensures that the underlying parent [RenderObject]
  /// knows where a child needs to move to in a linked list by providing its new
  /// previous sibling.
5469
  @protected
5470
  List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element> forgottenChildren }) {
5471
    assert(oldChildren != null);
5472
    assert(newWidgets != null);
5473

5474 5475
    Element replaceWithNullIfForgotten(Element child) {
      return forgottenChildren != null && forgottenChildren.contains(child) ? null : child;
5476 5477
    }

5478 5479 5480 5481
    // This attempts to diff the new child list (newWidgets) with
    // the old child list (oldChildren), and produce a new list of elements to
    // be the new list of child elements of this element. The called of this
    // method is expected to update this render object accordingly.
5482

5483
    // The cases it tries to optimize for are:
5484 5485 5486 5487 5488 5489 5490 5491
    //  - the old list is empty
    //  - the lists are identical
    //  - there is an insertion or removal of one or more widgets in
    //    only one place in the list
    // If a widget with a key is in both lists, it will be synced.
    // Widgets without keys might be synced but there is no guarantee.

    // The general approach is to sync the entire new list backwards, as follows:
5492 5493 5494 5495 5496
    // 1. Walk the lists from the top, syncing nodes, until you no longer have
    //    matching nodes.
    // 2. Walk the lists from the bottom, without syncing nodes, until you no
    //    longer have matching nodes. We'll sync these nodes at the end. We
    //    don't sync them now because we want to sync all the nodes in order
5497
    //    from beginning to end.
5498 5499 5500 5501
    // At this point we narrowed the old and new lists to the point
    // where the nodes no longer match.
    // 3. Walk the narrowed part of the old list to get the list of
    //    keys and sync null with non-keyed items.
5502
    // 4. Walk the narrowed part of the new list forwards:
5503
    //     * Sync non-keyed items with null
5504
    //     * Sync keyed items with the source if it exists, else with null.
5505
    // 5. Walk the bottom of the list again, syncing the nodes.
5506 5507 5508
    // 6. Sync null with any items in the list of keys that are still
    //    mounted.

5509 5510
    int newChildrenTop = 0;
    int oldChildrenTop = 0;
5511 5512
    int newChildrenBottom = newWidgets.length - 1;
    int oldChildrenBottom = oldChildren.length - 1;
5513

5514
    final List<Element> newChildren = oldChildren.length == newWidgets.length ?
5515
        oldChildren : List<Element>(newWidgets.length);
5516 5517 5518 5519 5520

    Element previousChild;

    // Update the top of the list.
    while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
5521 5522
      final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
      final Widget newWidget = newWidgets[newChildrenTop];
5523 5524
      assert(oldChild == null || oldChild._debugLifecycleState == _ElementLifecycle.active);
      if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
5525
        break;
5526
      final Element newChild = updateChild(oldChild, newWidget, IndexedSlot<Element>(newChildrenTop, previousChild));
5527 5528 5529 5530 5531
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
      oldChildrenTop += 1;
5532 5533
    }

5534 5535
    // Scan the bottom of the list.
    while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
5536 5537
      final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);
      final Widget newWidget = newWidgets[newChildrenBottom];
5538 5539
      assert(oldChild == null || oldChild._debugLifecycleState == _ElementLifecycle.active);
      if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
5540
        break;
5541 5542
      oldChildrenBottom -= 1;
      newChildrenBottom -= 1;
5543 5544
    }

5545
    // Scan the old children in the middle of the list.
5546
    final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
5547
    Map<Key, Element> oldKeyedChildren;
5548
    if (haveOldChildren) {
5549
      oldKeyedChildren = <Key, Element>{};
5550
      while (oldChildrenTop <= oldChildrenBottom) {
5551
        final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
5552 5553 5554 5555 5556
        assert(oldChild == null || oldChild._debugLifecycleState == _ElementLifecycle.active);
        if (oldChild != null) {
          if (oldChild.widget.key != null)
            oldKeyedChildren[oldChild.widget.key] = oldChild;
          else
Hixie's avatar
Hixie committed
5557
            deactivateChild(oldChild);
5558
        }
5559
        oldChildrenTop += 1;
5560
      }
5561 5562
    }

5563 5564
    // Update the middle of the list.
    while (newChildrenTop <= newChildrenBottom) {
5565
      Element oldChild;
5566
      final Widget newWidget = newWidgets[newChildrenTop];
5567
      if (haveOldChildren) {
5568
        final Key key = newWidget.key;
5569
        if (key != null) {
5570
          oldChild = oldKeyedChildren[key];
5571
          if (oldChild != null) {
5572
            if (Widget.canUpdate(oldChild.widget, newWidget)) {
5573 5574 5575 5576
              // we found a match!
              // remove it from oldKeyedChildren so we don't unsync it later
              oldKeyedChildren.remove(key);
            } else {
5577
              // Not a match, let's pretend we didn't see it for now.
5578
              oldChild = null;
5579
            }
5580 5581
          }
        }
5582
      }
5583
      assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));
5584
      final Element newChild = updateChild(oldChild, newWidget, IndexedSlot<Element>(newChildrenTop, previousChild));
5585 5586
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
5587 5588 5589
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
5590
    }
5591

5592
    // We've scanned the whole list.
5593 5594 5595 5596 5597 5598 5599 5600
    assert(oldChildrenTop == oldChildrenBottom + 1);
    assert(newChildrenTop == newChildrenBottom + 1);
    assert(newWidgets.length - newChildrenTop == oldChildren.length - oldChildrenTop);
    newChildrenBottom = newWidgets.length - 1;
    oldChildrenBottom = oldChildren.length - 1;

    // Update the bottom of the list.
    while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
5601
      final Element oldChild = oldChildren[oldChildrenTop];
5602
      assert(replaceWithNullIfForgotten(oldChild) != null);
5603
      assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
5604
      final Widget newWidget = newWidgets[newChildrenTop];
5605
      assert(Widget.canUpdate(oldChild.widget, newWidget));
5606
      final Element newChild = updateChild(oldChild, newWidget, IndexedSlot<Element>(newChildrenTop, previousChild));
5607 5608
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
5609 5610 5611 5612
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
      oldChildrenTop += 1;
5613 5614
    }

5615
    // Clean up any of the remaining middle nodes from the old list.
Ian Hickson's avatar
Ian Hickson committed
5616
    if (haveOldChildren && oldKeyedChildren.isNotEmpty) {
5617
      for (final Element oldChild in oldKeyedChildren.values) {
5618
        if (forgottenChildren == null || !forgottenChildren.contains(oldChild))
Hixie's avatar
Hixie committed
5619
          deactivateChild(oldChild);
5620
      }
5621 5622
    }

5623
    return newChildren;
5624 5625
  }

5626
  @override
5627 5628
  void deactivate() {
    super.deactivate();
5629 5630 5631
    assert(!renderObject.attached,
      'A RenderObject was still attached when attempting to deactivate its '
      'RenderObjectElement: $renderObject');
5632 5633
  }

5634
  @override
5635 5636
  void unmount() {
    super.unmount();
5637 5638 5639
    assert(!renderObject.attached,
      'A RenderObject was still attached when attempting to unmount its '
      'RenderObjectElement: $renderObject');
5640 5641 5642
    widget.didUnmountRenderObject(renderObject);
  }

5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667
  void _updateParentData(ParentDataWidget<ParentData> parentDataWidget) {
    bool applyParentData = true;
    assert(() {
      try {
        if (!parentDataWidget.debugIsValidRenderObject(renderObject)) {
          applyParentData = false;
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('Incorrect use of ParentDataWidget.'),
            ...parentDataWidget._debugDescribeIncorrectParentDataType(
              parentData: renderObject.parentData,
              parentDataCreator: _ancestorRenderObjectElement.widget,
              ownershipChain: ErrorDescription(debugGetCreatorChain(10)),
            ),
          ]);
        }
      } on FlutterError catch (e) {
        // Catching the exception directly to avoid activating the ErrorWidget.
        // Since the tree is in a broken state, adding the ErrorWidget would
        // cause more exceptions.
        _debugReportException(ErrorSummary('while applying parent data.'), e, e.stackTrace);
      }
      return true;
    }());
    if (applyParentData)
      parentDataWidget.applyParentData(renderObject);
Hixie's avatar
Hixie committed
5668 5669
  }

5670
  @override
5671 5672 5673 5674 5675
  void _updateSlot(dynamic newSlot) {
    assert(slot != newSlot);
    super._updateSlot(newSlot);
    assert(slot == newSlot);
    _ancestorRenderObjectElement.moveChildRenderObject(renderObject, slot);
Hixie's avatar
Hixie committed
5676 5677
  }

5678
  @override
5679 5680 5681 5682 5683
  void attachRenderObject(dynamic newSlot) {
    assert(_ancestorRenderObjectElement == null);
    _slot = newSlot;
    _ancestorRenderObjectElement = _findAncestorRenderObjectElement();
    _ancestorRenderObjectElement?.insertChildRenderObject(renderObject, newSlot);
5684
    final ParentDataElement<ParentData> parentDataElement = _findAncestorParentDataElement();
5685
    if (parentDataElement != null)
5686
      _updateParentData(parentDataElement.widget);
5687 5688
  }

5689
  @override
Hixie's avatar
Hixie committed
5690
  void detachRenderObject() {
5691 5692 5693 5694
    if (_ancestorRenderObjectElement != null) {
      _ancestorRenderObjectElement.removeChildRenderObject(renderObject);
      _ancestorRenderObjectElement = null;
    }
5695
    _slot = null;
Hixie's avatar
Hixie committed
5696 5697
  }

5698 5699
  /// Insert the given child into [renderObject] at the given slot.
  ///
5700
  /// {@template flutter.widgets.slots}
5701 5702
  /// The semantics of `slot` are determined by this element. For example, if
  /// this element has a single child, the slot should always be null. If this
5703 5704 5705
  /// element has a list of children, the previous sibling element wrapped in an
  /// [IndexedSlot] is a convenient value for the slot.
  /// {@endtemplate}
5706
  @protected
5707
  void insertChildRenderObject(covariant RenderObject child, covariant dynamic slot);
5708

5709 5710 5711 5712
  /// Move the given child to the given slot.
  ///
  /// The given child is guaranteed to have [renderObject] as its parent.
  ///
5713
  /// {@macro flutter.widgets.slots}
Ian Hickson's avatar
Ian Hickson committed
5714 5715 5716 5717 5718 5719 5720 5721 5722
  ///
  /// This method is only ever called if [updateChild] can end up being called
  /// with an existing [Element] child and a `slot` that differs from the slot
  /// that element was previously given. [MultiChildRenderObjectElement] does this,
  /// for example. [SingleChildRenderObjectElement] does not (since the `slot` is
  /// always null). An [Element] that has a specific set of slots with each child
  /// always having the same slot (and where children in different slots are never
  /// compared against each other for the purposes of updating one slot with the
  /// element from another slot) would never call this.
5723
  @protected
5724
  void moveChildRenderObject(covariant RenderObject child, covariant dynamic slot);
5725

5726 5727 5728
  /// Remove the given child from [renderObject].
  ///
  /// The given child is guaranteed to have [renderObject] as its parent.
5729
  @protected
5730
  void removeChildRenderObject(covariant RenderObject child);
Hixie's avatar
Hixie committed
5731

5732
  @override
5733 5734
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
5735
    properties.add(DiagnosticsProperty<RenderObject>('renderObject', renderObject, defaultValue: null));
5736 5737
  }
}
Hixie's avatar
Hixie committed
5738

5739
/// The element at the root of the tree.
5740 5741 5742 5743
///
/// Only root elements may have their owner set explicitly. All other
/// elements inherit their owner from their parent.
abstract class RootRenderObjectElement extends RenderObjectElement {
5744
  /// Initializes fields for subclasses.
5745
  RootRenderObjectElement(RenderObjectWidget widget) : super(widget);
5746

5747 5748 5749 5750 5751 5752 5753 5754
  /// Set the owner of the element. The owner will be propagated to all the
  /// descendants of this element.
  ///
  /// The owner manages the dirty elements list.
  ///
  /// The [WidgetsBinding] introduces the primary owner,
  /// [WidgetsBinding.buildOwner], and assigns it to the widget tree in the call
  /// to [runApp]. The binding is responsible for driving the build pipeline by
5755
  /// calling the build owner's [BuildOwner.buildScope] method. See
5756
  /// [WidgetsBinding.drawFrame].
5757 5758 5759 5760 5761 5762
  void assignOwner(BuildOwner owner) {
    _owner = owner;
  }

  @override
  void mount(Element parent, dynamic newSlot) {
5763
    // Root elements should never have parents.
5764 5765 5766 5767 5768 5769
    assert(parent == null);
    assert(newSlot == null);
    super.mount(parent, newSlot);
  }
}

5770
/// An [Element] that uses a [LeafRenderObjectWidget] as its configuration.
5771
class LeafRenderObjectElement extends RenderObjectElement {
5772
  /// Creates an element that uses the given widget as its configuration.
5773
  LeafRenderObjectElement(LeafRenderObjectWidget widget) : super(widget);
Hixie's avatar
Hixie committed
5774

5775
  @override
5776
  void forgetChild(Element child) {
5777
    assert(false);
5778
    super.forgetChild(child);
5779 5780
  }

5781
  @override
5782
  void insertChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
5783 5784 5785
    assert(false);
  }

5786
  @override
5787
  void moveChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
5788 5789 5790
    assert(false);
  }

5791
  @override
5792 5793 5794
  void removeChildRenderObject(RenderObject child) {
    assert(false);
  }
5795 5796 5797 5798 5799

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    return widget.debugDescribeChildren();
  }
Hixie's avatar
Hixie committed
5800 5801
}

5802
/// An [Element] that uses a [SingleChildRenderObjectWidget] as its configuration.
5803 5804 5805 5806 5807 5808
///
/// The child is optional.
///
/// This element subclass can be used for RenderObjectWidgets whose
/// RenderObjects use the [RenderObjectWithChildMixin] mixin. Such widgets are
/// expected to inherit from [SingleChildRenderObjectWidget].
5809
class SingleChildRenderObjectElement extends RenderObjectElement {
5810
  /// Creates an element that uses the given widget as its configuration.
5811
  SingleChildRenderObjectElement(SingleChildRenderObjectWidget widget) : super(widget);
5812

5813
  @override
5814
  SingleChildRenderObjectWidget get widget => super.widget as SingleChildRenderObjectWidget;
Hixie's avatar
Hixie committed
5815

5816
  Element _child;
Hixie's avatar
Hixie committed
5817

5818
  @override
5819 5820 5821
  void visitChildren(ElementVisitor visitor) {
    if (_child != null)
      visitor(_child);
Hixie's avatar
Hixie committed
5822 5823
  }

5824
  @override
5825
  void forgetChild(Element child) {
5826 5827
    assert(child == _child);
    _child = null;
5828
    super.forgetChild(child);
5829 5830
  }

5831
  @override
5832 5833 5834
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _child = updateChild(_child, widget.child, null);
5835 5836
  }

5837
  @override
5838
  void update(SingleChildRenderObjectWidget newWidget) {
5839 5840 5841
    super.update(newWidget);
    assert(widget == newWidget);
    _child = updateChild(_child, widget.child, null);
Hixie's avatar
Hixie committed
5842 5843
  }

5844
  @override
5845
  void insertChildRenderObject(RenderObject child, dynamic slot) {
5846
    final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject as RenderObjectWithChildMixin<RenderObject>;
Hixie's avatar
Hixie committed
5847
    assert(slot == null);
5848
    assert(renderObject.debugValidateChild(child));
5849
    renderObject.child = child;
Hixie's avatar
Hixie committed
5850
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
5851 5852
  }

5853
  @override
5854 5855 5856 5857
  void moveChildRenderObject(RenderObject child, dynamic slot) {
    assert(false);
  }

5858
  @override
5859
  void removeChildRenderObject(RenderObject child) {
5860
    final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject as RenderObjectWithChildMixin<RenderObject>;
5861
    assert(renderObject.child == child);
Hixie's avatar
Hixie committed
5862
    renderObject.child = null;
Hixie's avatar
Hixie committed
5863
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
5864 5865 5866
  }
}

5867
/// An [Element] that uses a [MultiChildRenderObjectWidget] as its configuration.
5868 5869 5870 5871 5872
///
/// This element subclass can be used for RenderObjectWidgets whose
/// RenderObjects use the [ContainerRenderObjectMixin] mixin with a parent data
/// type that implements [ContainerParentDataMixin<RenderObject>]. Such widgets
/// are expected to inherit from [MultiChildRenderObjectWidget].
5873 5874 5875 5876 5877 5878 5879
///
/// See also:
///
/// * [IndexedSlot], which is used as [Element.slot]s for the children of a
///   [MultiChildRenderObjectElement].
/// * [RenderObjectElement.updateChildren], which discusses why [IndexedSlot]
///   is used for the slots of the children.
5880
class MultiChildRenderObjectElement extends RenderObjectElement {
5881
  /// Creates an element that uses the given widget as its configuration.
5882 5883 5884
  MultiChildRenderObjectElement(MultiChildRenderObjectWidget widget)
    : assert(!debugChildrenHaveDuplicateKeys(widget, widget.children)),
      super(widget);
Hixie's avatar
Hixie committed
5885

5886
  @override
5887
  MultiChildRenderObjectWidget get widget => super.widget as MultiChildRenderObjectWidget;
5888

5889 5890 5891 5892 5893
  /// The current list of children of this element.
  ///
  /// This list is filtered to hide elements that have been forgotten (using
  /// [forgetChild]).
  @protected
5894
  @visibleForTesting
5895 5896
  Iterable<Element> get children => _children.where((Element child) => !_forgottenChildren.contains(child));

5897
  List<Element> _children;
5898
  // We keep a set of forgotten children to avoid O(n^2) work walking _children
5899
  // repeatedly to remove children.
5900
  final Set<Element> _forgottenChildren = HashSet<Element>();
Hixie's avatar
Hixie committed
5901

5902
  @override
5903
  void insertChildRenderObject(RenderObject child, IndexedSlot<Element> slot) {
5904 5905
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject =
      this.renderObject as ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>;
5906
    assert(renderObject.debugValidateChild(child));
5907
    renderObject.insert(child, after: slot?.value?.renderObject);
Hixie's avatar
Hixie committed
5908
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
5909 5910
  }

5911
  @override
5912
  void moveChildRenderObject(RenderObject child, IndexedSlot<Element> slot) {
5913 5914
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject =
      this.renderObject as ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>;
5915
    assert(child.parent == renderObject);
5916
    renderObject.move(child, after: slot?.value?.renderObject);
Hixie's avatar
Hixie committed
5917
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
5918 5919
  }

5920
  @override
5921
  void removeChildRenderObject(RenderObject child) {
5922 5923
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject =
      this.renderObject as ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>;
5924 5925
    assert(child.parent == renderObject);
    renderObject.remove(child);
Hixie's avatar
Hixie committed
5926
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
5927 5928
  }

5929
  @override
5930
  void visitChildren(ElementVisitor visitor) {
5931
    for (final Element child in _children) {
5932
      if (!_forgottenChildren.contains(child))
5933 5934 5935 5936
        visitor(child);
    }
  }

5937
  @override
5938
  void forgetChild(Element child) {
5939
    assert(_children.contains(child));
5940 5941
    assert(!_forgottenChildren.contains(child));
    _forgottenChildren.add(child);
5942
    super.forgetChild(child);
5943 5944
  }

5945
  @override
5946 5947
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
5948
    _children = List<Element>(widget.children.length);
5949
    Element previousChild;
5950
    for (int i = 0; i < _children.length; i += 1) {
5951
      final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element>(i, previousChild));
5952 5953
      _children[i] = newChild;
      previousChild = newChild;
5954 5955 5956
    }
  }

5957
  @override
5958
  void update(MultiChildRenderObjectWidget newWidget) {
5959 5960
    super.update(newWidget);
    assert(widget == newWidget);
5961 5962
    _children = updateChildren(_children, widget.children, forgottenChildren: _forgottenChildren);
    _forgottenChildren.clear();
5963
  }
5964 5965
}

5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976
/// A wrapper class for the [Element] that is the creator of a [RenderObject].
///
/// Attaching a [DebugCreator] attach the [RenderObject] will lead to better error
/// message.
class DebugCreator {
  /// Create a [DebugCreator] instance with input [Element].
  DebugCreator(this.element);

  /// The creator of the [RenderObject].
  final Element element;

5977 5978 5979 5980
  @override
  String toString() => element.debugGetCreatorChain(12);
}

5981
FlutterErrorDetails _debugReportException(
5982
  DiagnosticsNode context,
5983 5984
  dynamic exception,
  StackTrace stack, {
5985
  InformationCollector informationCollector,
Ian Hickson's avatar
Ian Hickson committed
5986
}) {
5987
  final FlutterErrorDetails details = FlutterErrorDetails(
5988 5989 5990
    exception: exception,
    stack: stack,
    library: 'widgets library',
Ian Hickson's avatar
Ian Hickson committed
5991 5992
    context: context,
    informationCollector: informationCollector,
5993 5994 5995
  );
  FlutterError.reportError(details);
  return details;
5996
}
5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034

/// A value for [Element.slot] used for children of
/// [MultiChildRenderObjectElement]s.
///
/// A slot for a [MultiChildRenderObjectElement] consists of an [index]
/// identifying where the child occupying this slot is located in the
/// [MultiChildRenderObjectElement]'s child list and an arbitrary [value] that
/// can further define where the child occupying this slot fits in its
/// parent's child list.
///
/// See also:
///
///  * [RenderObjectElement.updateChildren], which discusses why this class is
///    used as slot values for the children of a [MultiChildRenderObjectElement].
@immutable
class IndexedSlot<T> {
  /// Creates an [IndexedSlot] with the provided [index] and slot [value].
  const IndexedSlot(this.index, this.value);

  /// Information to define where the child occupying this slot fits in its
  /// parent's child list.
  final T value;

  /// The index of this slot in the parent's child list.
  final int index;

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is IndexedSlot
        && index == other.index
        && value == other.value;
  }

  @override
  int get hashCode => hashValues(index, value);
}