framework.dart 193 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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

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

17
export 'package:flutter/foundation.dart' show FlutterError, debugPrint, debugPrintStack;
18
export 'package:flutter/foundation.dart' show VoidCallback, ValueChanged, ValueGetter, ValueSetter;
19
export 'package:flutter/foundation.dart' show DiagnosticLevel;
20
export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;
21
export 'package:flutter/rendering.dart' show RenderObject, RenderBox, debugDumpRenderTree, debugDumpLayerTree;
22

23 24 25 26 27 28 29 30 31
// 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
32 33
// KEYS

34
/// A key that is only equal to itself.
Hixie's avatar
Hixie committed
35
class UniqueKey extends LocalKey {
36
  /// Creates a key that is equal only to itself.
37
  // ignore: prefer_const_constructors_in_immutables , never use const for this class
38
  UniqueKey();
39 40

  @override
41
  String toString() => '[#${shortHash(this)}]';
Hixie's avatar
Hixie committed
42 43
}

44
/// A key that takes its identity from the object used as its value.
45
///
46 47
/// Used to tie the identity of a widget to the identity of an object used to
/// generate that widget.
48 49
///
/// See also the discussions at [Key] and [Widget.key].
Hixie's avatar
Hixie committed
50
class ObjectKey extends LocalKey {
51
  /// Creates a key that uses [identical] on [value] for its [operator==].
Hixie's avatar
Hixie committed
52
  const ObjectKey(this.value);
53

54
  /// The object whose identity is used by this key's [operator==].
55
  final Object value;
56 57

  @override
Hixie's avatar
Hixie committed
58
  bool operator ==(dynamic other) {
Ian Hickson's avatar
Ian Hickson committed
59
    if (other.runtimeType != runtimeType)
Hixie's avatar
Hixie committed
60 61 62 63
      return false;
    final ObjectKey typedOther = other;
    return identical(value, typedOther.value);
  }
64 65

  @override
Ian Hickson's avatar
Ian Hickson committed
66
  int get hashCode => hashValues(runtimeType, identityHashCode(value));
67 68

  @override
Ian Hickson's avatar
Ian Hickson committed
69 70
  String toString() {
    if (runtimeType == ObjectKey)
71 72
      return '[${describeIdentity(value)}]';
    return '[$runtimeType ${describeIdentity(value)}]';
Ian Hickson's avatar
Ian Hickson committed
73
  }
74 75
}

76
/// A key that is unique across the entire app.
77
///
78
/// Global keys uniquely identify elements. Global keys provide access to other
79 80
/// objects that are associated with elements, such as the a [BuildContext] and,
/// for [StatefulWidget]s, a [State].
81 82 83 84 85 86 87
///
/// 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.
///
88
/// Global keys are relatively expensive. If you don't need any of the features
89 90
/// listed above, consider using a [Key], [ValueKey], [ObjectKey], or
/// [UniqueKey] instead.
91 92 93
///
/// You cannot simultaneously include two widgets in the tree with the same
/// global key. Attempting to do so will assert at runtime.
94 95
///
/// See also the discussion at [Widget.key].
pq's avatar
pq committed
96
@optionalTypeArgs
97
abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
98 99
  /// Creates a [LabeledGlobalKey], which is a [GlobalKey] with a label used for
  /// debugging.
100 101 102
  ///
  /// The label is purely for debugging and not used for comparing the identity
  /// of the key.
103
  factory GlobalKey({ String debugLabel }) => new LabeledGlobalKey<T>(debugLabel);
104

105 106
  /// Creates a global key without a label.
  ///
107
  /// Used by subclasses because the factory constructor shadows the implicit
108
  /// constructor.
109
  const GlobalKey.constructor() : super.empty();
Ian Hickson's avatar
Ian Hickson committed
110

111
  static final Map<GlobalKey, Element> _registry = <GlobalKey, Element>{};
112
  static final Set<GlobalKey> _removedKeys = new HashSet<GlobalKey>();
113
  static final Set<Element> _debugIllFatedElements = new HashSet<Element>();
114
  static final Map<GlobalKey, Element> _debugReservations = <GlobalKey, Element>{};
115

116
  void _register(Element element) {
117 118
    assert(() {
      if (_registry.containsKey(this)) {
119 120 121 122
        assert(element.widget != null);
        assert(_registry[this].widget != null);
        assert(element.widget.runtimeType != _registry[this].widget.runtimeType);
        _debugIllFatedElements.add(_registry[this]);
123 124
      }
      return true;
125
    }());
126
    _registry[this] = element;
127 128
  }

129
  void _unregister(Element element) {
130
    assert(() {
131 132 133 134
      if (_registry.containsKey(this) && _registry[this] != element) {
        assert(element.widget != null);
        assert(_registry[this].widget != null);
        assert(element.widget.runtimeType != _registry[this].widget.runtimeType);
135 136
      }
      return true;
137
    }());
138
    if (_registry[this] == element) {
139 140 141 142 143
      _registry.remove(this);
      _removedKeys.add(this);
    }
  }

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
  void _debugReserveFor(Element parent) {
    assert(() {
      assert(parent != null);
      if (_debugReservations.containsKey(this) && _debugReservations[this] != parent) {
        // It's possible for an element to get built multiple times in one
        // frame, in which case it'll reserve the same child's key multiple
        // times. We catch multiple children of one widget having the same key
        // by verifying that an element never steals elements from itself, so we
        // don't care to verify that here as well.
        final String older = _debugReservations[this].toString();
        final String newer = parent.toString();
        if (older != newer) {
          throw new FlutterError(
            'Multiple widgets used the same GlobalKey.\n'
            'The key $this was used by multiple widgets. The parents of those widgets were:\n'
            '- $older\n'
            '- $newer\n'
            'A GlobalKey can only be specified on one widget at a time in the widget tree.'
          );
        }
        throw new FlutterError(
          'Multiple widgets used the same GlobalKey.\n'
          'The key $this was used by multiple widgets. The parents of those widgets were '
          'different widgets that both had the following description:\n'
          '  $newer\n'
          'A GlobalKey can only be specified on one widget at a time in the widget tree.'
        );
      }
      _debugReservations[this] = parent;
      return true;
174
    }());
175 176 177 178 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
  }

  static void _debugVerifyIllFatedPopulation() {
    assert(() {
      Map<GlobalKey, Set<Element>> duplicates;
      for (Element element in _debugIllFatedElements) {
        if (element._debugLifecycleState != _ElementLifecycle.defunct) {
          assert(element != null);
          assert(element.widget != null);
          assert(element.widget.key != null);
          final GlobalKey key = element.widget.key;
          assert(_registry.containsKey(key));
          duplicates ??= <GlobalKey, Set<Element>>{};
          final Set<Element> elements = duplicates.putIfAbsent(key, () => new HashSet<Element>());
          elements.add(element);
          elements.add(_registry[key]);
        }
      }
      _debugIllFatedElements.clear();
      _debugReservations.clear();
      if (duplicates != null) {
        final StringBuffer buffer = new StringBuffer();
        buffer.writeln('Multiple widgets used the same GlobalKey.\n');
        for (GlobalKey key in duplicates.keys) {
          final Set<Element> elements = duplicates[key];
          buffer.writeln('The key $key was used by ${elements.length} widgets:');
          for (Element element in elements)
            buffer.writeln('- $element');
        }
        buffer.write('A GlobalKey can only be specified on one widget at a time in the widget tree.');
        throw new FlutterError(buffer.toString());
      }
      return true;
208
    }());
209 210
  }

211
  Element get _currentElement => _registry[this];
212 213 214 215 216

  /// 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.
217
  BuildContext get currentContext => _currentElement;
218 219 220 221 222

  /// 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.
223
  Widget get currentWidget => _currentElement?.widget;
224 225 226 227 228

  /// 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
229
  /// associated [State] object is not a subtype of `T`.
230
  T get currentState {
231
    final Element element = _currentElement;
232
    if (element is StatefulElement) {
233 234
      final StatefulElement statefulElement = element;
      final State state = statefulElement.state;
235 236
      if (state is T)
        return state;
237
    }
238
    return null;
239
  }
240 241
}

242 243 244 245
/// 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.
246
@optionalTypeArgs
247
class LabeledGlobalKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
248 249 250
  /// Creates a global key with a debugging label.
  ///
  /// The label does not affect the key's identity.
251
  // ignore: prefer_const_constructors_in_immutables , never use const for this class
252
  LabeledGlobalKey(this._debugLabel) : super.constructor();
253

254
  final String _debugLabel;
255 256

  @override
Ian Hickson's avatar
Ian Hickson committed
257
  String toString() {
258
    final String label = _debugLabel != null ? ' $_debugLabel' : '';
259
    if (runtimeType == LabeledGlobalKey)
260 261
      return '[GlobalKey#${shortHash(this)}$label]';
    return '[${describeIdentity(this)}$label]';
Ian Hickson's avatar
Ian Hickson committed
262
  }
263 264
}

265
/// A global key that takes its identity from the object used as its value.
266
///
267 268
/// 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
269
///
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
/// 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
286
/// Any [GlobalObjectKey] created for the same value will match.
287 288
@optionalTypeArgs
class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
289
  /// Creates a global key that uses [identical] on [value] for its [operator==].
Adam Barth's avatar
Adam Barth committed
290
  const GlobalObjectKey(this.value) : super.constructor();
291 292

  /// The object whose identity is used by this key's [operator==].
293
  final Object value;
294 295

  @override
Hixie's avatar
Hixie committed
296
  bool operator ==(dynamic other) {
Ian Hickson's avatar
Ian Hickson committed
297
    if (other.runtimeType != runtimeType)
Hixie's avatar
Hixie committed
298
      return false;
299
    final GlobalObjectKey<T> typedOther = other;
Hixie's avatar
Hixie committed
300 301
    return identical(value, typedOther.value);
  }
302 303

  @override
304
  int get hashCode => identityHashCode(value);
305 306

  @override
307
  String toString() => '[$runtimeType ${describeIdentity(value)}]';
Eric Seidel's avatar
Eric Seidel committed
308 309
}

Ian Hickson's avatar
Ian Hickson committed
310
/// This class is a work-around for the "is" operator not accepting a variable value as its right operand
pq's avatar
pq committed
311
@optionalTypeArgs
Ian Hickson's avatar
Ian Hickson committed
312
class TypeMatcher<T> {
313
  /// Creates a type matcher for the given type parameter.
Ian Hickson's avatar
Ian Hickson committed
314
  const TypeMatcher();
315

316
  /// Returns true if the given object is of type `T`.
Ian Hickson's avatar
Ian Hickson committed
317 318
  bool check(dynamic object) => object is T;
}
319

320 321 322 323 324 325
/// 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.
///
326 327 328 329 330
/// 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.
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
///
/// 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:
///
348 349 350 351 352 353
///  * [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.
354
@immutable
355
abstract class Widget extends DiagnosticableTree {
356
  /// Initializes [key] for subclasses.
357
  const Widget({ this.key });
358 359 360 361 362 363 364 365 366

  /// 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.
367
  ///
368 369 370 371 372 373 374 375 376 377 378
  /// 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.
  ///
  /// See also the discussions at [Key] and [GlobalKey].
379
  final Key key;
380

381
  /// Inflates this configuration to a concrete instance.
382 383 384 385 386 387
  ///
  /// 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.
388
  @protected
389
  Element createElement();
390

391
  /// A short, textual description of this widget.
392
  @override
393 394 395 396
  String toStringShort() {
    return key == null ? '$runtimeType' : '$runtimeType-$key';
  }

397
  @override
398 399 400
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
    description.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
401
  }
402

403

404 405 406 407 408 409
  /// 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==].
410 411 412 413
  ///
  /// 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.
414
  static bool canUpdate(Widget oldWidget, Widget newWidget) {
415 416
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
417
  }
418
}
419

420 421 422 423 424 425
/// 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
426
/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
427 428 429 430 431 432 433 434
///
/// 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].
///
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
/// ## 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.
///
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
/// ## Sample code
///
/// The following is a skeleton of a stateless widget subclass called `GreenFrog`:
///
/// ```dart
/// class GreenFrog extends StatelessWidget {
///   const GreenFrog({ Key key }) : super(key: key);
///
///   @override
///   Widget build(BuildContext context) {
///     return new Container(color: const Color(0xFF2DBD3A));
///   }
/// }
/// ```
///
/// Normally widgets have more constructor arguments, each of which corresponds
/// to a `final` property. The next example shows the more generic widget `Frog`
/// which can be given a color and a child:
///
/// ```dart
/// class Frog extends StatelessWidget {
///   const Frog({
///     Key key,
///     this.color: const Color(0xFF2DBD3A),
///     this.child,
///   }) : super(key: key);
///
///   final Color color;
///
///   final Widget child;
///
///   @override
///   Widget build(BuildContext context) {
///     return new Container(color: color, child: child);
///   }
/// }
/// ```
///
/// 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.
///
518 519
/// See also:
///
520 521 522 523
///  * [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.
524
abstract class StatelessWidget extends Widget {
525
  /// Initializes [key] for subclasses.
526
  const StatelessWidget({ Key key }) : super(key: key);
527

528 529
  /// Creates a [StatelessElement] to manage this widget's location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
530
  /// It is uncommon for subclasses to override this method.
531
  @override
532
  StatelessElement createElement() => new StatelessElement(this);
533

534 535
  /// Describes the part of the user interface represented by this widget.
  ///
Adam Barth's avatar
Adam Barth committed
536
  /// The framework calls this method when this widget is inserted into the
537 538
  /// tree in a given [BuildContext] and when the dependencies of this widget
  /// change (e.g., an [InheritedWidget] referenced by this widget changes).
539
  ///
540
  /// The framework replaces the subtree below this widget with the widget
Adam Barth's avatar
Adam Barth committed
541
  /// returned by this method, either by updating the existing subtree or by
542
  /// removing the subtree and inflating a new subtree, depending on whether the
Adam Barth's avatar
Adam Barth committed
543 544
  /// widget returned by this method can update the root of the existing
  /// subtree, as determined by calling [Widget.canUpdate].
545
  ///
Adam Barth's avatar
Adam Barth committed
546
  /// Typically implementations return a newly created constellation of widgets
547 548 549 550 551 552
  /// 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
553 554 555
  /// 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.
556 557 558 559 560 561 562 563 564 565
  ///
  /// 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
  ///   [BuildContext.inheritFromWidgetOfExactType].
  ///
  /// If a widget's [build] method is to depend on anything else, use a
  /// [StatefulWidget] instead.
566 567 568 569
  ///
  /// See also:
  ///
  ///  * The discussion on performance considerations at [StatelessWidget].
570
  @protected
571 572
  Widget build(BuildContext context);
}
573

574 575
/// A widget that has mutable state.
///
576 577 578 579
/// 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].
580 581 582 583 584
///
/// 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
585
/// entirely of [RenderObjectWidget]s, which describe concrete [RenderObject]s).
586
///
587
/// Stateful widget are useful when the part of the user interface you are
588 589 590 591 592 593 594
/// 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].
///
/// [StatefulWidget] instances themselves are immutable and store their mutable
595 596 597 598 599 600
/// 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
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
/// [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
619
/// eligible for grafting, the widget must be inserted into the new location in
620 621
/// the same animation frame in which it was removed from the old location.
///
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
/// ## 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
637
/// application's lifetime, and it is therefore important to minimize the impact
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
/// 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.)
///
682 683
/// ## Sample code
///
684
/// The following is a skeleton of a stateful widget subclass called `YellowBird`:
685 686
///
/// ```dart
687 688
/// class YellowBird extends StatefulWidget {
///   const YellowBird({ Key key }) : super(key: key);
689 690
///
///   @override
691
///   _YellowBirdState createState() => new _YellowBirdState();
692 693
/// }
///
694
/// class _YellowBirdState extends State<YellowBird> {
695 696
///   @override
///   Widget build(BuildContext context) {
697
///     return new Container(color: const Color(0xFFFFE306));
698 699 700 701 702 703 704 705
///   }
/// }
/// ```
///
/// 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.
///
706
/// The next example shows the more generic widget `Bird` which can be given a
707 708 709 710
/// color and a child, and which has some internal state with a method that
/// can be called to mutate it:
///
/// ```dart
711 712
/// class Bird extends StatefulWidget {
///   const Bird({
713
///     Key key,
714
///     this.color: const Color(0xFFFFE306),
715 716 717 718 719 720 721
///     this.child,
///   }) : super(key: key);
///
///   final Color color;
///
///   final Widget child;
///
722
///   _BirdState createState() => new _BirdState();
723 724
/// }
///
725
/// class _BirdState extends State<Bird> {
726 727 728 729 730 731 732 733 734 735
///   double _size = 1.0;
///
///   void grow() {
///     setState(() { _size += 0.1; });
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     return new Container(
///       color: widget.color,
736
///       transform: new Matrix4.diagonal3Values(_size, _size, 1.0),
737 738 739 740 741 742 743 744 745 746 747
///       child: widget.child,
///     );
///   }
/// }
/// ```
///
/// 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.
///
748 749
/// See also:
///
750 751 752 753 754
///  * [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.
755
abstract class StatefulWidget extends Widget {
756
  /// Initializes [key] for subclasses.
757
  const StatefulWidget({ Key key }) : super(key: key);
758

759 760
  /// Creates a [StatefulElement] to manage this widget's location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
761
  /// It is uncommon for subclasses to override this method.
762
  @override
763
  StatefulElement createElement() => new StatefulElement(this);
764

765 766
  /// Creates the mutable state for this widget at a given location in the tree.
  ///
Adam Barth's avatar
Adam Barth committed
767
  /// Subclasses should override this method to return a newly created
768 769 770 771 772 773
  /// instance of their associated [State] subclass:
  ///
  /// ```dart
  /// @override
  /// _MyState createState() => new _MyState();
  /// ```
774
  ///
Adam Barth's avatar
Adam Barth committed
775
  /// The framework can call this method multiple times over the lifetime of
776 777 778 779 780 781
  /// 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.
782
  @protected
783 784
  State createState();
}
785

786
/// Tracks the lifecycle of [State] objects when asserts are enabled.
787
enum _StateLifecycle {
788 789
  /// The [State] object has been created. [State.initState] is called at this
  /// time.
790
  created,
791

Adam Barth's avatar
Adam Barth committed
792
  /// The [State.initState] method has been called but the [State] object is
793
  /// not yet ready to build. [State.didChangeDependencies] is called at this time.
794
  initialized,
795 796 797

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

Adam Barth's avatar
Adam Barth committed
800
  /// The [State.dispose] method has been called and the [State] object is
801
  /// no longer able to build.
802 803
  defunct,
}
804

805
/// The signature of [State.setState] functions.
806 807
typedef void StateSetter(VoidCallback fn);

808
/// The logic and internal state for a [StatefulWidget].
Adam Barth's avatar
Adam Barth committed
809
///
810 811 812 813
/// 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
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
///
/// [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
837
///    [widget] properties, respectively, when the [initState] method is
Adam Barth's avatar
Adam Barth committed
838
///    called.
839 840
///  * The framework calls [didChangeDependencies]. Subclasses of [State] should
///    override [didChangeDependencies] to perform initialization involving
841
///    [InheritedWidget]s. If [BuildContext.inheritFromWidgetOfExactType] is
842
///    called, the [didChangeDependencies] method will be called again if the
843
///    inherited widgets subsequently change or if the widget moves in the tree.
Adam Barth's avatar
Adam Barth committed
844 845 846
///  * 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
847
///    spontaneously request to rebuild their subtree by callings their
Adam Barth's avatar
Adam Barth committed
848 849 850 851 852
///    [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
853 854 855 856
///    [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
857
///    associated widget (e.g., to start implicit animations). The framework
Ian Hickson's avatar
Ian Hickson committed
858 859
///    always calls [build] after calling [didUpdateWidget], which means any
///    calls to [setState] in [didUpdateWidget] are redundant.
Adam Barth's avatar
Adam Barth committed
860 861
///  * 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
862
///    or [Widget.key]), the framework calls the [deactivate] method. Subclasses
Adam Barth's avatar
Adam Barth committed
863 864 865 866 867 868 869 870 871 872 873 874
///    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
875
///    animation frame, the framework will call [dispose], which indicates that
Adam Barth's avatar
Adam Barth committed
876 877 878 879 880 881 882 883 884 885
///    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:
///
886 887
///  * [StatefulWidget], where the current configuration of a [State] is hosted,
///    and whose documentation has sample code for [State].
888 889 890 891
///  * [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.
892
///  * [Widget], for an overview of widgets in general.
pq's avatar
pq committed
893
@optionalTypeArgs
894
abstract class State<T extends StatefulWidget> extends Diagnosticable {
Adam Barth's avatar
Adam Barth committed
895 896 897 898 899
  /// 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
900 901 902 903
  /// 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.
904 905 906
  T get widget => _widget;
  T _widget;

Adam Barth's avatar
Adam Barth committed
907 908 909 910
  /// 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.
911
  _StateLifecycle _debugLifecycleState = _StateLifecycle.created;
912

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

Adam Barth's avatar
Adam Barth committed
917 918 919 920 921 922 923 924 925 926
  /// 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].
927
  BuildContext get context => _element;
928
  StatefulElement _element;
929

Adam Barth's avatar
Adam Barth committed
930 931 932 933 934 935 936 937 938
  /// 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.
939
  bool get mounted => _element != null;
940

Adam Barth's avatar
Adam Barth committed
941 942
  /// Called when this object is inserted into the tree.
  ///
943 944 945
  /// The framework will call this method exactly once for each [State] object
  /// it creates.
  ///
Adam Barth's avatar
Adam Barth committed
946 947
  /// Override this method to perform initialization that depends on the
  /// location at which this object was inserted into the tree (i.e., [context])
948
  /// or on the widget used to configure this object (i.e., [widget]).
Adam Barth's avatar
Adam Barth committed
949
  ///
950 951 952 953 954
  /// 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 the [State] should
  /// subscribe to that object during [initState], unsubscribe from the old
  /// object and subscribe to the new object when it changes in
955
  /// [didUpdateWidget], and then unsubscribe from the object in [dispose].
956
  ///
957
  /// You cannot use [BuildContext.inheritFromWidgetOfExactType] from this
958
  /// method. However, [didChangeDependencies] will be called immediately
959 960 961
  /// following this method, and [BuildContext.inheritFromWidgetOfExactType] can
  /// be used there.
  ///
962 963
  /// If you override this, make sure your method starts with a call to
  /// super.initState().
964
  @protected
965
  @mustCallSuper
966 967
  void initState() {
    assert(_debugLifecycleState == _StateLifecycle.created);
968
  }
969

970
  /// Called whenever the widget configuration changes.
Adam Barth's avatar
Adam Barth committed
971 972
  ///
  /// If the parent widget rebuilds and request that this location in the tree
973 974
  /// update to display a new widget with the same [runtimeType] and
  /// [Widget.key], the framework will update the [widget] property of this
975
  /// [State] object to refer to the new widget and then call this method
976
  /// with the previous widget as an argument.
Adam Barth's avatar
Adam Barth committed
977
  ///
978 979
  /// Override this method to respond when the [widget] changes (e.g., to start
  /// implicit animations).
Adam Barth's avatar
Adam Barth committed
980
  ///
981 982
  /// 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
983
  ///
984 985 986 987 988
  /// 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 the [State] should
  /// subscribe to that object during [initState], unsubscribe from the old
  /// object and subscribe to the new object when it changes in
989
  /// [didUpdateWidget], and then unsubscribe from the object in [dispose].
990
  ///
Adam Barth's avatar
Adam Barth committed
991
  /// If you override this, make sure your method starts with a call to
992
  /// super.didUpdateWidget(oldWidget).
993
  @mustCallSuper
994
  @protected
995 996
  void didUpdateWidget(covariant T oldWidget) { }

997 998 999 1000 1001 1002 1003
  /// Called whenever the application is reassembled during debugging.
  ///
  /// 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).
  ///
  /// In addition to this method being invoked, it is guaranteed that the
1004
  /// [build] method will be invoked when a reassemble is signaled. Most
1005 1006 1007 1008 1009 1010 1011 1012
  /// widgets therefore do not need to do anything in the [reassemble] method.
  ///
  /// 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.
  ///
  /// See also:
  ///
1013 1014
  /// * [BindingBase.reassembleApplication].
  /// * [Image], which uses this to reload images.
1015 1016 1017 1018
  @protected
  @mustCallSuper
  void reassemble() { }

Adam Barth's avatar
Adam Barth committed
1019 1020 1021 1022
  /// 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]:
1023
  ///
1024
  /// ```dart
Adam Barth's avatar
Adam Barth committed
1025
  /// setState(() { _myState = newValue });
1026
  /// ```
1027
  ///
1028 1029 1030 1031
  /// 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
1032 1033 1034 1035 1036 1037 1038 1039 1040
  /// 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.
  ///
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
  /// 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
  /// Future<Null> _incrementCounter() async {
  ///   setState(() {
  ///     _counter++;
  ///   });
1052 1053
  ///   Directory directory = await getApplicationDocumentsDirectory();
  ///   final String dirName = directory.path;
1054 1055 1056 1057 1058
  ///   await new File('$dir/counter.txt').writeAsString('$_counter');
  ///   return null;
  /// }
  /// ```
  ///
Adam Barth's avatar
Adam Barth committed
1059 1060 1061
  /// 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.
1062
  @protected
1063
  void setState(VoidCallback fn) {
1064
    assert(fn != null);
1065 1066
    assert(() {
      if (_debugLifecycleState == _StateLifecycle.defunct) {
1067
        throw new FlutterError(
1068
          'setState() called after dispose(): $this\n'
1069
          'This error happens if you call setState() on a State object for a widget that '
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
          '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. 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.\n'
          '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, '
1080
          'consider breaking the reference to this object during dispose().'
1081 1082 1083
        );
      }
      return true;
1084
    }());
1085
    final dynamic result = fn() as dynamic;
1086 1087 1088 1089
    assert(() {
      if (result is Future) {
        throw new FlutterError(
          'setState() callback argument returned a Future.\n'
1090
          'The setState() method on $this was called with a closure or method that '
1091 1092 1093 1094 1095 1096 1097 1098 1099
          'returned a Future. Maybe it is marked as "async".\n'
          '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().'
        );
      }
      // We ignore other types of return values so that you can do things like:
      //   setState(() => x = 3);
      return true;
1100
    }());
1101
    _element.markNeedsBuild();
1102
  }
1103

1104 1105
  /// Called when this object is removed from the tree.
  ///
Adam Barth's avatar
Adam Barth committed
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
  /// 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().
1123 1124 1125
  ///
  /// See also [dispose], which is called after [deactivate] if the widget is
  /// removed from the tree permanently.
1126
  @protected
1127
  @mustCallSuper
1128 1129 1130
  void deactivate() { }

  /// Called when this object is removed from the tree permanently.
Adam Barth's avatar
Adam Barth committed
1131 1132 1133 1134 1135 1136 1137 1138 1139
  ///
  /// 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).
1140
  ///
1141 1142 1143 1144 1145
  /// 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 the [State] should
  /// subscribe to that object during [initState], unsubscribe from the old
  /// object and subscribe to the new object when it changes in
1146
  /// [didUpdateWidget], and then unsubscribe from the object in [dispose].
1147
  ///
1148 1149
  /// If you override this, make sure to end your method with a call to
  /// super.dispose().
1150 1151
  ///
  /// See also [deactivate], which is called prior to [dispose].
1152
  @protected
1153
  @mustCallSuper
1154 1155
  void dispose() {
    assert(_debugLifecycleState == _StateLifecycle.ready);
1156
    assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
1157 1158
  }

Adam Barth's avatar
Adam Barth committed
1159
  /// Describes the part of the user interface represented by this widget.
1160
  ///
Adam Barth's avatar
Adam Barth committed
1161
  /// The framework calls this method in a number of different situations:
1162
  ///
Adam Barth's avatar
Adam Barth committed
1163
  ///  * After calling [initState].
1164
  ///  * After calling [didUpdateWidget].
Adam Barth's avatar
Adam Barth committed
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
  ///  * 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].
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
  ///
  /// ## Design discussion
  ///
  /// ### Why is the [build] method on [State], and not [StatefulWidget]?
  ///
  /// Putting a `Widget build(BuildContext context)` method on [State] rather
  /// putting a `Widget build(BuildContext context, State state)` method on
  /// [StatefulWidget] gives developers more flexibility when subclassing
  /// [StatefulWidget].
  ///
  /// For example, [AnimatedWidget] is a subclass of [StatefulWidget] that
  /// introduces an abstract `Widget build(BuildContext context)` method for its
  /// subclasses to implement.  If [StatefulWidget] already had a [build] method
  /// 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
  /// [StatefulWidget] in a similar manner.  If the [build] method were on
  /// [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,
  /// the `$color` in the print function refers to blue, as expected.  Now,
  /// suppose the parent rebuilds `MyButton` with green.  The closure created by
  /// 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) {
1244
  ///     ... () { print("color: ${widget.color}"); } ...
1245 1246 1247 1248 1249 1250
  ///   }
  /// }
  /// ```
  ///
  /// Now when the parent rebuilds `MyButton` with green, the closure created by
  /// the first build still refers to [State] object, which is preserved across
1251 1252
  /// rebuilds, but the framework has updated that [State] object's [widget]
  /// property to refer to the new `MyButton` instance and `${widget.color}`
1253
  /// prints green, as expected.
1254 1255 1256 1257
  ///
  /// See also:
  ///
  ///  * The discussion on performance considerations at [StatefulWidget].
1258
  @protected
1259
  Widget build(BuildContext context);
1260

1261
  /// Called when a dependency of this [State] object changes.
Adam Barth's avatar
Adam Barth committed
1262 1263 1264 1265 1266
  ///
  /// 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.
  ///
1267 1268 1269
  /// This method is also called immediately after [initState]. It is safe to
  /// call [BuildContext.inheritFromWidgetOfExactType] from this method.
  ///
Adam Barth's avatar
Adam Barth committed
1270 1271 1272 1273 1274
  /// 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.
1275
  @protected
1276
  @mustCallSuper
1277
  void didChangeDependencies() { }
1278

1279 1280 1281
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
Hixie's avatar
Hixie committed
1282
    assert(() {
1283
      description.add(new EnumProperty<_StateLifecycle>('lifecycle state', _debugLifecycleState, defaultValue: _StateLifecycle.ready));
Hixie's avatar
Hixie committed
1284
      return true;
1285
    }());
1286 1287
    description.add(new ObjectFlagProperty<T>('_widget', _widget, ifNull: 'no widget'));
    description.add(new ObjectFlagProperty<StatefulElement>('_element', _element, ifNull: 'not mounted'));
1288
  }
1289
}
1290

1291 1292
/// A widget that has a child widget provided to it, instead of building a new
/// widget.
1293 1294 1295
///
/// Useful as a base class for other widgets, such as [InheritedWidget] and
/// [ParentDataWidget].
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
///
/// 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.
1309 1310
abstract class ProxyWidget extends Widget {
  /// Creates a widget that has exactly one child widget.
1311
  const ProxyWidget({ Key key, @required this.child }) : super(key: key);
1312

1313
  /// The widget below this widget in the tree.
1314
  final Widget child;
1315 1316
}

1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
/// 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.
///
/// A [ParentDataWidget] is specific to a particular kind of [RenderObject], and
/// thus also to a particular [RenderObjectWidget] class. That class is `T`, the
/// [ParentDataWidget] type argument.
1327 1328 1329 1330 1331 1332 1333 1334
///
/// ## Sample code
///
/// This example shows how you would build a [ParentDataWidget] to configure a
/// `FrogJar` widget's children by specifying a [Size] for each one.
///
/// ```dart
/// class FrogSize extends ParentDataWidget<FrogJar> {
1335
///   FrogSize({
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
///     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();
///     }
///   }
/// }
/// ```
///
/// 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
///    [RenderObject.parentData] slots.
///  * [RenderObjectWidget], the class for widgets that wrap [RenderObject]s.
///    The `T` type parameter for [ParentDataWidget] is a [RenderObjectWidget].
///  * [StatefulWidget] and [State], for widgets that can build differently
///    several times over their lifetime.
1367
abstract class ParentDataWidget<T extends RenderObjectWidget> extends ProxyWidget {
1368 1369
  /// 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
1370
  const ParentDataWidget({ Key key, Widget child })
1371 1372
    : super(key: key, child: child);

1373
  @override
1374
  ParentDataElement<T> createElement() => new ParentDataElement<T>(this);
1375

1376
  /// Subclasses should override this method to return true if the given
1377 1378
  /// ancestor is a RenderObjectWidget that wraps a RenderObject that can handle
  /// the kind of ParentData widget that the ParentDataWidget subclass handles.
1379
  ///
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
  /// The default implementation uses the type argument.
  bool debugIsValidAncestor(RenderObjectWidget ancestor) {
    assert(T != dynamic);
    assert(T != RenderObjectWidget);
    return ancestor is T;
  }

  /// Subclasses should override this to describe the requirements for using the
  /// ParentDataWidget subclass. It is called when debugIsValidAncestor()
  /// returned false for an ancestor, or when there are extraneous
1390
  /// [ParentDataWidget]s in the ancestor chain.
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
  String debugDescribeInvalidAncestorChain({ String description, String ownershipChain, bool foundValidAncestor, Iterable<Widget> badAncestors }) {
    assert(T != dynamic);
    assert(T != RenderObjectWidget);
    String result;
    if (!foundValidAncestor) {
      result = '$runtimeType widgets must be placed inside $T widgets.\n'
               '$description has no $T ancestor at all.\n';
    } else {
      assert(badAncestors.isNotEmpty);
      result = '$runtimeType widgets must be placed directly inside $T widgets.\n'
               '$description has a $T ancestor, but there are other widgets between them:\n';
      for (Widget ancestor in badAncestors) {
        if (ancestor.runtimeType == runtimeType) {
1404
          result += '- $ancestor (this is a different $runtimeType than the one with the problem)\n';
1405
        } else {
1406
          result += '- $ancestor\n';
1407 1408 1409 1410 1411 1412 1413
        }
      }
      result += 'These widgets cannot come between a $runtimeType and its $T.\n';
    }
    result += 'The ownership chain for the parent of the offending $runtimeType was:\n  $ownershipChain';
    return result;
  }
1414

1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
  /// 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.
1433
  @protected
1434
  void applyParentData(RenderObject renderObject);
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447

  /// 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;
1448
}
1449

1450 1451 1452 1453 1454 1455 1456
/// Base class for widgets that efficiently propagate information down the tree.
///
/// To obtain the nearest instance of a particular type of inherited widget from
/// a build context, use [BuildContext.inheritFromWidgetOfExactType].
///
/// Inherited widgets, when referenced in this way, will cause the consumer to
/// rebuild when the inherited widget itself changes state.
1457 1458 1459 1460 1461 1462 1463
///
/// ## Sample code
///
/// The following is a skeleton of an inherited widget called `FrogColor`:
///
/// ```dart
/// class FrogColor extends InheritedWidget {
1464
///   const FrogColor({
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
///     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) {
///     return context.inheritFromWidgetOfExactType(FrogColor);
///   }
///
///   @override
///   bool updateShouldNotify(FrogColor old) => color != old.color;
/// }
/// ```
///
/// The convention is to provide a static method `of` on the [InheritedWidget]
/// which does the call to [BuildContext.inheritFromWidgetOfExactType]. This
/// allows the class to define its own fallback logic in the case of there not
/// being a widget in scope. In the example above, the value returned will be
/// 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
1491
/// of the `FrogColor` widget.
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
///
/// 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
/// for that inherited widget using [BuildContext.inheritFromWidgetOfExactType]
/// and then returns the [ThemeData].
///
/// 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.
1507
abstract class InheritedWidget extends ProxyWidget {
1508 1509
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1510 1511
  const InheritedWidget({ Key key, Widget child })
    : super(key: key, child: child);
1512

1513
  @override
1514
  InheritedElement createElement() => new InheritedElement(this);
Eric Seidel's avatar
Eric Seidel committed
1515

1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
  /// 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
  /// held by this widget is the same as the data held by `oldWidget`, then then
  /// we do not need to rebuild the widgets that inherited the data held by
  /// `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.
1528
  @protected
1529
  bool updateShouldNotify(covariant InheritedWidget oldWidget);
1530
}
1531

1532 1533 1534 1535
/// RenderObjectWidgets provide the configuration for [RenderObjectElement]s,
/// which wrap [RenderObject]s, which provide the actual rendering of the
/// application.
abstract class RenderObjectWidget extends Widget {
1536 1537
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1538 1539
  const RenderObjectWidget({ Key key }) : super(key: key);

1540
  /// RenderObjectWidgets always inflate to a [RenderObjectElement] subclass.
1541
  @override
1542 1543
  RenderObjectElement createElement();

1544 1545 1546
  /// Creates an instance of the [RenderObject] class that this
  /// [RenderObjectWidget] represents, using the configuration described by this
  /// [RenderObjectWidget].
1547 1548 1549 1550 1551 1552
  ///
  /// 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].
1553
  @protected
1554
  RenderObject createRenderObject(BuildContext context);
1555

1556 1557 1558
  /// 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].
1559 1560 1561 1562 1563 1564
  ///
  /// 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].
1565
  @protected
1566
  void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
1567

1568 1569 1570
  /// 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].
1571
  @protected
1572
  void didUnmountRenderObject(covariant RenderObject renderObject) { }
1573 1574 1575 1576 1577
}

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

1582
  @override
1583 1584 1585 1586 1587 1588
  LeafRenderObjectElement createElement() => new LeafRenderObjectElement(this);
}

/// A superclass for RenderObjectWidgets that configure RenderObject subclasses
/// that have a single child slot. (This superclass only provides the storage
/// for that child, it doesn't actually provide the updating logic.)
1589
abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
1590 1591
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
1592
  const SingleChildRenderObjectWidget({ Key key, this.child }) : super(key: key);
1593

1594
  /// The widget below this widget in the tree.
1595 1596
  final Widget child;

1597
  @override
1598
  SingleChildRenderObjectElement createElement() => new SingleChildRenderObjectElement(this);
1599 1600 1601 1602 1603 1604 1605
}

/// A superclass for RenderObjectWidgets that configure RenderObject subclasses
/// 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.)
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
1606
  /// Initializes fields for subclasses.
1607 1608 1609
  ///
  /// The [children] argument must not be null and must not contain any null
  /// objects.
1610
  MultiChildRenderObjectWidget({ Key key, this.children: const <Widget>[] })
1611
    : assert(children != null),
1612 1613
      assert(!children.any((Widget child) => child == null)), // https://github.com/dart-lang/sdk/issues/29276
      super(key: key);
1614

1615 1616 1617 1618 1619
  /// The widgets below this widget in the tree.
  ///
  /// If this list is going to be mutated, it is usually wise to put [Key]s on
  /// the widgets, so that the framework can match old configurations to new
  /// configurations and maintain the underlying render objects.
1620 1621
  final List<Widget> children;

1622
  @override
1623 1624 1625
  MultiChildRenderObjectElement createElement() => new MultiChildRenderObjectElement(this);
}

Hixie's avatar
Hixie committed
1626 1627 1628

// ELEMENTS

1629 1630
enum _ElementLifecycle {
  initial,
1631 1632
  active,
  inactive,
1633
  defunct,
1634 1635
}

1636
class _InactiveElements {
1637
  bool _locked = false;
1638
  final Set<Element> _elements = new HashSet<Element>();
1639

1640
  void _unmount(Element element) {
1641
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
1642 1643 1644 1645 1646 1647
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle) {
        if (element.widget.key is GlobalKey)
          debugPrint('Discarding $element from inactive elements list.');
      }
      return true;
1648
    }());
1649 1650
    element.visitChildren((Element child) {
      assert(child._parent == element);
1651
      _unmount(child);
1652
    });
1653 1654
    element.unmount();
    assert(element._debugLifecycleState == _ElementLifecycle.defunct);
1655 1656
  }

1657
  void _unmountAll() {
1658 1659 1660
    _locked = true;
    final List<Element> elements = _elements.toList()..sort(Element._sort);
    _elements.clear();
1661
    try {
1662
      elements.reversed.forEach(_unmount);
1663
    } finally {
1664
      assert(_elements.isEmpty);
1665 1666
      _locked = false;
    }
1667 1668
  }

1669
  void _deactivateRecursively(Element element) {
1670 1671 1672
    assert(element._debugLifecycleState == _ElementLifecycle.active);
    element.deactivate();
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
1673
    element.visitChildren(_deactivateRecursively);
1674
    assert(() { element.debugDeactivated(); return true; }());
1675 1676
  }

1677 1678 1679 1680
  void add(Element element) {
    assert(!_locked);
    assert(!_elements.contains(element));
    assert(element._parent == null);
1681
    if (element._active)
1682
      _deactivateRecursively(element);
1683 1684
    _elements.add(element);
  }
1685 1686 1687 1688 1689 1690 1691 1692

  void remove(Element element) {
    assert(!_locked);
    assert(_elements.contains(element));
    assert(element._parent == null);
    _elements.remove(element);
    assert(!element._active);
  }
1693 1694 1695 1696 1697 1698

  bool debugContains(Element element) {
    bool result;
    assert(() {
      result = _elements.contains(element);
      return true;
1699
    }());
1700 1701
    return result;
  }
1702 1703
}

1704 1705 1706 1707 1708 1709
/// 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.
1710
typedef void ElementVisitor(Element element);
1711

1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
/// 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
///     return new Scaffold(
///       appBar: new AppBar(title: new Text('Demo')),
///       body: new Builder(
///         builder: (BuildContext context) {
///           return new FlatButton(
///             child: new Text('BUTTON'),
///             onPressed: () {
///               // here, Scaffold.of(context) returns the locally created Scaffold
///               Scaffold.of(context).showSnackBar(new SnackBar(
///                 content: new Text('Hello.')
///               ));
///             }
///           );
///         }
///       )
///     );
///   }
/// ```
///
/// 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.
1775
abstract class BuildContext {
1776
  /// The current configuration of the [Element] that is this [BuildContext].
1777
  Widget get widget;
1778

1779 1780 1781 1782
  /// The [BuildOwner] for this context. The [BuildOwner] is in charge of
  /// managing the rendering pipeline for this context.
  BuildOwner get owner;

1783 1784 1785 1786 1787 1788
  /// 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
1789 1790
  /// complete. It is therefore not valid to call this from a build method.
  /// It should only be called from interaction event handlers (e.g.
1791 1792 1793
  /// gesture callbacks) or layout or paint callbacks.
  ///
  /// If the render object is a [RenderBox], which is the common case, then the
1794 1795 1796 1797
  /// 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).
1798
  ///
1799 1800
  /// For details on the different phases of a frame, see the discussion at
  /// [WidgetsBinding.drawFrame].
1801 1802 1803 1804 1805
  ///
  /// 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.
1806
  RenderObject findRenderObject();
1807

1808 1809 1810
  /// The size of the [RenderBox] returned by [findRenderObject].
  ///
  /// This getter will only return a valid result after the layout phase is
1811 1812
  /// complete. It is therefore not valid to call this from a build method.
  /// It should only be called from paint callbacks or interaction event
1813 1814
  /// handlers (e.g. gesture callbacks).
  ///
1815 1816
  /// For details on the different phases of a frame, see the discussion at
  /// [WidgetsBinding.drawFrame].
1817 1818 1819
  ///
  /// This getter will only return a valid result if [findRenderObject] actually
  /// returns a [RenderBox]. If [findRenderObject] returns a render object that
1820
  /// is not a subtype of [RenderBox] (e.g., [RenderView]), this getter will
1821 1822 1823 1824 1825 1826 1827 1828
  /// 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;

1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
  /// 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.
  ///
  /// This is typically called implicitly from `of()` static methods, e.g.
  /// [Theme.of].
  ///
  /// This should not be called from widget constructors or from
  /// [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
1842
  /// (directly or indirectly) from build methods, layout and paint callbacks, or
1843
  /// from [State.didChangeDependencies].
1844
  ///
1845 1846 1847 1848 1849
  /// 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
  /// in [State.didChangeDependencies].
  ///
1850 1851 1852 1853 1854 1855
  /// It is also possible to call this 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.
  ///
  /// Calling this method is O(1) with a small constant factor, but will lead to
  /// the widget being rebuilt more often.
1856 1857
  ///
  /// Once a widget registers a dependency on a particular type by calling this
1858
  /// method, it will be rebuilt, and [State.didChangeDependencies] will be
1859 1860 1861
  /// 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).
Ian Hickson's avatar
Ian Hickson committed
1862
  InheritedWidget inheritFromWidgetOfExactType(Type targetType);
1863

Matt Perry's avatar
Matt Perry committed
1864 1865 1866 1867 1868 1869
  /// Obtains the element corresponding to the nearest widget of the given type,
  /// which must be the type of a concrete [InheritedWidget] subclass.
  ///
  /// Calling this method is O(1) with a small constant factor.
  ///
  /// This method does not establish a relationship with the target in the way
1870
  /// that [inheritFromWidgetOfExactType] does.
1871 1872 1873 1874 1875
  ///
  /// 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
  /// by calling [inheritFromWidgetOfExactType] in [State.didChangeDependencies].
Matt Perry's avatar
Matt Perry committed
1876 1877
  InheritedElement ancestorInheritedElementForWidgetOfExactType(Type targetType);

1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
  /// Returns the nearest ancestor widget of the given type, which must be the
  /// type of a concrete [Widget] subclass.
  ///
  /// 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.
  /// In general, [inheritFromWidgetOfExactType] is more useful. This method is
  /// appropriate when used in interaction event handlers (e.g. gesture
  /// callbacks), or for performing one-off tasks.
  ///
  /// 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.
1890 1891 1892 1893 1894
  ///
  /// 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
  /// by calling [inheritFromWidgetOfExactType] in [State.didChangeDependencies].
Ian Hickson's avatar
Ian Hickson committed
1895
  Widget ancestorWidgetOfExactType(Type targetType);
1896 1897 1898 1899 1900 1901 1902

  /// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
  /// that matches the given [TypeMatcher].
  ///
  /// 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.
  /// In general, [inheritFromWidgetOfExactType] is more appropriate for such
1903
  /// cases. This method is useful for changing the state of an ancestor widget in
1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915
  /// 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.
1916
  ///
1917 1918 1919 1920 1921
  /// 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
  /// by calling [inheritFromWidgetOfExactType] in [State.didChangeDependencies].
  ///
1922 1923 1924 1925 1926
  /// Example:
  ///
  /// ```dart
  /// context.ancestorStateOfType(const TypeMatcher<ScrollableState>());
  /// ```
Ian Hickson's avatar
Ian Hickson committed
1927
  State ancestorStateOfType(TypeMatcher matcher);
1928

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
  /// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
  /// that matches the given [TypeMatcher].
  ///
  /// Functions the same way as [ancestorStateOfType] but keeps visiting subsequent
  /// ancestors until there are none of the type matching [TypeMatcher] remaining.
  /// Then returns the last one found.
  ///
  /// This operation is O(N) as well though N is the entire widget tree rather than
  /// a subtree.
  State rootAncestorStateOfType(TypeMatcher matcher);

1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
  /// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
  /// that matches the given [TypeMatcher].
  ///
  /// 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.
  /// In general, [inheritFromWidgetOfExactType] is more appropriate for such
  /// 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.
  ///
1951 1952 1953 1954 1955
  /// 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
  /// by calling [inheritFromWidgetOfExactType] in [State.didChangeDependencies].
  ///
1956 1957 1958
  /// 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.
Ian Hickson's avatar
Ian Hickson committed
1959
  RenderObject ancestorRenderObjectOfType(TypeMatcher matcher);
1960 1961 1962 1963 1964 1965 1966 1967 1968 1969

  /// 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).
1970 1971 1972 1973 1974
  ///
  /// 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
  /// by calling [inheritFromWidgetOfExactType] in [State.didChangeDependencies].
1975
  void visitAncestorElements(bool visitor(Element element));
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995

  /// 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.
1996
  void visitChildElements(ElementVisitor visitor);
1997
}
1998

1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
/// 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
/// during debugging.
///
/// 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.
2015
class BuildOwner {
2016
  /// Creates an object that manages widgets.
2017 2018
  BuildOwner({ this.onBuildScheduled });

2019 2020
  /// Called on each build pass when the first buildable element is marked
  /// dirty.
2021 2022 2023 2024
  VoidCallback onBuildScheduled;

  final _InactiveElements _inactiveElements = new _InactiveElements();

2025
  final List<Element> _dirtyElements = <Element>[];
2026
  bool _scheduledFlushDirtyElements = false;
2027 2028
  bool _dirtyElementsNeedsResorting; // null means we're not in a buildScope

2029 2030 2031 2032 2033 2034 2035 2036
  /// 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.
  final FocusManager focusManager = new FocusManager();

2037
  /// Adds an element to the dirty elements list so that it will be rebuilt
2038
  /// when [WidgetsBinding.drawFrame] calls [buildScope].
2039
  void scheduleBuildFor(Element element) {
2040 2041
    assert(element != null);
    assert(element.owner == this);
2042
    assert(() {
2043 2044
      if (debugPrintScheduleBuildForStacks)
        debugPrintStack(label: 'scheduleBuildFor() called for $element${_dirtyElements.contains(element) ? " (ALREADY IN LIST)" : ""}');
2045 2046 2047
      if (!element.dirty) {
        throw new FlutterError(
          'scheduleBuildFor() called for a widget that is not marked as dirty.\n'
2048
          'The method was called for the following element:\n'
2049 2050 2051 2052 2053 2054 2055 2056 2057
          '  $element\n'
          'This element is not current marked as dirty. Make sure to set the dirty flag before '
          'calling scheduleBuildFor().\n'
          'If you did not attempt to call scheduleBuildFor() yourself, then this probably '
          'indicates a bug in the widgets framework. Please report it: '
          'https://github.com/flutter/flutter/issues/new'
        );
      }
      return true;
2058
    }());
2059 2060 2061 2062 2063 2064
    if (element._inDirtyList) {
      assert(() {
        if (debugPrintScheduleBuildForStacks)
          debugPrintStack(label: 'markNeedsToResortDirtyElements() called; _dirtyElementsNeedsResorting was $_dirtyElementsNeedsResorting (now true); dirty list is: $_dirtyElements');
        if (_dirtyElementsNeedsResorting == null) {
          throw new FlutterError(
2065 2066 2067
            'markNeedsToResortDirtyElements() called inappropriately.\n'
            'The markNeedsToResortDirtyElements() method should only be called while the '
            'buildScope() method is actively rebuilding the widget tree.'
2068 2069 2070
          );
        }
        return true;
2071
      }());
2072 2073 2074
      _dirtyElementsNeedsResorting = true;
      return;
    }
2075 2076
    if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      _scheduledFlushDirtyElements = true;
2077
      onBuildScheduled();
2078
    }
2079
    _dirtyElements.add(element);
2080
    element._inDirtyList = true;
2081 2082 2083 2084
    assert(() {
      if (debugPrintScheduleBuildForStacks)
        debugPrint('...dirty list is now: $_dirtyElements');
      return true;
2085
    }());
2086 2087 2088 2089
  }

  int _debugStateLockLevel = 0;
  bool get _debugStateLocked => _debugStateLockLevel > 0;
2090 2091 2092 2093 2094

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

2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
  /// 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;
2109
    }());
2110 2111 2112 2113 2114 2115
    try {
      callback();
    } finally {
      assert(() {
        _debugStateLockLevel -= 1;
        return true;
2116
      }());
2117 2118 2119 2120 2121 2122 2123
    }
    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.
2124
  ///
2125 2126
  /// This mechanism prevents build methods from transitively requiring other
  /// build methods to run, potentially causing infinite loops.
2127
  ///
2128 2129 2130 2131 2132 2133 2134 2135
  /// 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
2136
  /// each frame, in [WidgetsBinding.drawFrame].
2137 2138
  ///
  /// Only one [buildScope] can be active at a time.
2139
  ///
2140
  /// A [buildScope] implies a [lockState] scope as well.
2141 2142 2143 2144 2145
  ///
  /// 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.
2146
  void buildScope(Element context, [VoidCallback callback]) {
2147 2148 2149
    if (callback == null && _dirtyElements.isEmpty)
      return;
    assert(context != null);
2150
    assert(_debugStateLockLevel >= 0);
2151
    assert(!_debugBuilding);
2152
    assert(() {
2153 2154
      if (debugPrintBuildScope)
        debugPrint('buildScope called with context $context; dirty list is: $_dirtyElements');
2155
      _debugStateLockLevel += 1;
2156
      _debugBuilding = true;
2157
      return true;
2158
    }());
2159
    Timeline.startSync('Build', arguments: timelineWhitelistArguments);
2160
    try {
2161
      _scheduledFlushDirtyElements = true;
2162 2163
      if (callback != null) {
        assert(_debugStateLocked);
2164
        Element debugPreviousBuildTarget;
2165 2166 2167 2168 2169
        assert(() {
          context._debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
          debugPreviousBuildTarget = _debugCurrentBuildTarget;
          _debugCurrentBuildTarget = context;
         return true;
2170
        }());
2171
        _dirtyElementsNeedsResorting = false;
2172 2173 2174 2175 2176 2177 2178
        try {
          callback();
        } finally {
          assert(() {
            context._debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
            assert(_debugCurrentBuildTarget == context);
            _debugCurrentBuildTarget = debugPreviousBuildTarget;
2179
            _debugElementWasRebuilt(context);
2180
            return true;
2181
          }());
2182 2183
        }
      }
2184
      _dirtyElements.sort(Element._sort);
2185
      _dirtyElementsNeedsResorting = false;
2186 2187 2188 2189 2190 2191
      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
2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202
        try {
          _dirtyElements[index].rebuild();
        } catch (e, stack) {
          _debugReportException(
            'while rebuilding dirty elements', e, stack,
            informationCollector: (StringBuffer information) {
              information.writeln('The element being rebuilt at the time was index $index of $dirtyCount:');
              information.write('  ${_dirtyElements[index]}');
            }
          );
        }
2203
        index += 1;
2204
        if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting) {
2205
          _dirtyElements.sort(Element._sort);
2206
          _dirtyElementsNeedsResorting = false;
2207
          dirtyCount = _dirtyElements.length;
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
          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;
          }
2218 2219
        }
      }
2220
      assert(() {
2221
        if (_dirtyElements.any((Element element) => element._active && element.dirty)) {
2222 2223 2224 2225 2226 2227 2228 2229
          throw new FlutterError(
            'buildScope missed some dirty elements.\n'
            'This probably indicates that the dirty list should have been resorted but was not.\n'
            'The list of dirty elements at the end of the buildScope call was:\n'
            '  $_dirtyElements'
          );
        }
        return true;
2230
      }());
Ian Hickson's avatar
Ian Hickson committed
2231
    } finally {
2232
      for (Element element in _dirtyElements) {
2233 2234 2235 2236 2237
        assert(element._inDirtyList);
        element._inDirtyList = false;
      }
      _dirtyElements.clear();
      _scheduledFlushDirtyElements = false;
2238
      _dirtyElementsNeedsResorting = null;
2239 2240
      Timeline.finishSync();
      assert(_debugBuilding);
2241
      assert(() {
2242
        _debugBuilding = false;
2243
        _debugStateLockLevel -= 1;
2244 2245
        if (debugPrintBuildScope)
          debugPrint('buildScope finished');
2246
        return true;
2247
      }());
2248 2249 2250 2251
    }
    assert(_debugStateLockLevel >= 0);
  }

2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
  Map<Element, Set<GlobalKey>> _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans;

  void _debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(Element node, GlobalKey key) {
    _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans ??= new HashMap<Element, Set<GlobalKey>>();
    final Set<GlobalKey> keys = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans
      .putIfAbsent(node, () => new HashSet<GlobalKey>());
    keys.add(key);
  }

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

2265 2266
  /// Complete the element build pass by unmounting any elements that are no
  /// longer active.
2267
  ///
2268
  /// This is called by [WidgetsBinding.drawFrame].
2269
  ///
2270 2271
  /// In debug mode, this also runs some sanity checks, for example checking for
  /// duplicate global keys.
2272 2273 2274
  ///
  /// After the current call stack unwinds, a microtask that notifies listeners
  /// about changes to global keys will run.
2275
  void finalizeTree() {
2276
    Timeline.startSync('Finalize tree', arguments: timelineWhitelistArguments);
2277 2278
    try {
      lockState(() {
2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357
        _inactiveElements._unmountAll(); // this unregisters the GlobalKeys
      });
      assert(() {
        try {
          GlobalKey._debugVerifyIllFatedPopulation();
          if (_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans != null &&
              _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.isNotEmpty) {
            final Set<GlobalKey> keys = new HashSet<GlobalKey>();
            for (Element element in _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans.keys) {
              if (element._debugLifecycleState != _ElementLifecycle.defunct)
                keys.addAll(_debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans[element]);
            }
            if (keys.isNotEmpty) {
              final Map<String, int> keyStringCount = new HashMap<String, int>();
              for (String key in keys.map<String>((GlobalKey key) => key.toString())) {
                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;
              final Map<String, int> elementStringCount = new HashMap<String, int>();
              for (String element in elements.map<String>((Element element) => element.toString())) {
                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';
              throw new FlutterError(
                'Duplicate GlobalKey$s detected in widget tree.\n'
                '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  ")}\n'
                'A GlobalKey can only be specified on one widget at a time in the widget tree.'
              );
            }
          }
        } finally {
          _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans?.clear();
        }
        return true;
2358
      }());
2359 2360 2361 2362 2363
    } catch (e, stack) {
      _debugReportException('while finalizing the widget tree', e, stack);
    } finally {
      Timeline.finishSync();
    }
2364
  }
2365

2366 2367 2368
  /// Cause the entire subtree rooted at the given [Element] to be entirely
  /// rebuilt. This is used by development tools when the application code has
  /// changed, to cause the widget tree to pick up any changed implementations.
2369
  ///
2370
  /// This is expensive and should not be called except during development.
2371
  void reassemble(Element root) {
2372 2373 2374 2375 2376 2377 2378 2379
    Timeline.startSync('Dirty Element Tree');
    try {
      assert(root._parent == null);
      assert(root.owner == this);
      root._reassemble();
    } finally {
      Timeline.finishSync();
    }
2380
  }
2381 2382
}

2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395
/// 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:
2396
///
2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
///  * 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
///    the widget at this location in the tree, can do so by unmounting this
///    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
2419
///    on screen. An element can remain in the inactive state only until
2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432
///    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.
2433
abstract class Element extends DiagnosticableTree implements BuildContext {
2434
  /// Creates an element that uses the given widget as its configuration.
2435 2436
  ///
  /// Typically called by an override of [Widget.createElement].
2437 2438 2439
  Element(Widget widget)
    : assert(widget != null),
      _widget = widget;
2440

2441 2442
  Element _parent;

2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
  // Custom implementation of `operator ==` optimized for the ".of" pattern
  // used with `InheritedWidgets`.
  @override
  bool operator ==(Object other) => identical(this, other);

  // Custom implementation of hash code optimized for the ".of" pattern used
  // with `InheritedWidgets`.
  //
  // `Element.inheritFromWidgetOfExactType` relies heavily on hash-based
  // `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:
  //
  //  * https://www.dartlang.org/articles/dart-vm/numeric-computation, which
  //    explains how numbers are represented in Dart.
  @override
  int get hashCode => _cachedHash;
  final int _cachedHash = _nextHashCode = (_nextHashCode + 1) % 0xffffff;
  static int _nextHashCode = 1;

2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
  /// 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;

2480
  static int _sort(Element a, Element b) {
2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491
    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;
  }

2492
  /// The configuration for this element.
2493
  @override
2494 2495
  Widget get widget => _widget;
  Widget _widget;
2496

2497
  /// The object that manages the lifecycle of this element.
2498
  @override
2499
  BuildOwner get owner => _owner;
2500
  BuildOwner _owner;
2501

2502 2503
  bool _active = false;

2504
  @mustCallSuper
2505
  void _reassemble() {
2506
    markNeedsBuild();
2507 2508 2509 2510 2511
    visitChildren((Element child) {
      child._reassemble();
    });
  }

2512
  bool _debugIsInScope(Element target) {
2513 2514 2515 2516 2517 2518
    Element current = this;
    while (current != null) {
      if (target == current)
        return true;
      current = current._parent;
    }
2519 2520 2521
    return false;
  }

2522 2523 2524 2525 2526
  /// 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].
2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537
  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;
2538 2539
  }

2540 2541
  // This is used to verify that Element objects move through life in an
  // orderly fashion.
2542
  _ElementLifecycle _debugLifecycleState = _ElementLifecycle.initial;
2543

2544 2545
  /// Calls the argument for each child. Must be overridden by subclasses that
  /// support having children.
2546 2547 2548
  ///
  /// There is no guaranteed order in which the children will be visited, though
  /// it should be consistent over time.
2549 2550 2551 2552 2553
  ///
  /// 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.
2554
  void visitChildren(ElementVisitor visitor) { }
2555

2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576
  /// 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:
  ///
  /// - [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.
  void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
2577

2578
  /// Wrapper around [visitChildren] for [BuildContext].
2579
  @override
2580
  void visitChildElements(ElementVisitor visitor) {
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590
    assert(() {
      if (owner == null || !owner._debugStateLocked)
        return true;
      throw new FlutterError(
        'visitChildElements() called during build.\n'
        'The BuildContext.visitChildElements() method can\'t be called during '
        '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.'
      );
2591
    }());
2592 2593 2594
    visitChildren(visitor);
  }

2595 2596
  /// Update the given child with the given new configuration.
  ///
2597 2598
  /// 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.
2599
  ///
2600 2601
  /// 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`.
2602
  ///
2603
  /// If the `newWidget` is null, and the `child` is not null, then we need to
2604 2605
  /// remove it because it no longer has a configuration.
  ///
2606 2607 2608 2609 2610
  /// 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.
2611
  ///
2612 2613
  /// If both are null, then we don't have a child and won't have a child, so we
  /// do nothing.
2614
  ///
2615
  /// The [updateChild] method returns the new child, if it had to create one,
2616 2617
  /// 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.
2618
  ///
2619
  /// The following table summarizes the above:
2620
  ///
2621 2622 2623 2624 2625
  /// <table>
  /// <tr><th><th>`newWidget == null`<th>`newWidget != null`
  /// <tr><th>`child == null`<td>Returns null.<td>Returns new [Element].
  /// <tr><th>`child != null`<td>Old child is removed, returns null.<td>Old child updated if possible, returns child or new [Element].
  /// </table>
2626
  @protected
2627
  Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
2628 2629 2630 2631 2632 2633
    assert(() {
      if (newWidget != null && newWidget.key is GlobalKey) {
        final GlobalKey key = newWidget.key;
        key._debugReserveFor(this);
      }
      return true;
2634
    }());
2635 2636
    if (newWidget == null) {
      if (child != null)
Hixie's avatar
Hixie committed
2637
        deactivateChild(child);
2638 2639 2640 2641 2642 2643 2644 2645
      return null;
    }
    if (child != null) {
      if (child.widget == newWidget) {
        if (child.slot != newSlot)
          updateSlotForChild(child, newSlot);
        return child;
      }
2646
      if (Widget.canUpdate(child.widget, newWidget)) {
2647 2648 2649 2650
        if (child.slot != newSlot)
          updateSlotForChild(child, newSlot);
        child.update(newWidget);
        assert(child.widget == newWidget);
2651 2652 2653
        assert(() {
          child.owner._debugElementWasRebuilt(child);
          return true;
2654
        }());
2655 2656
        return child;
      }
Hixie's avatar
Hixie committed
2657
      deactivateChild(child);
2658 2659
      assert(child._parent == null);
    }
Hixie's avatar
Hixie committed
2660
    return inflateWidget(newWidget, newSlot);
2661 2662
  }

2663 2664 2665 2666 2667
  /// 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
2668
  /// more easily be initialized in the constructor.
2669 2670 2671
  ///
  /// This method transitions the element from the "initial" lifecycle state to
  /// the "active" lifecycle state.
2672
  @mustCallSuper
2673 2674 2675 2676
  void mount(Element parent, dynamic newSlot) {
    assert(_debugLifecycleState == _ElementLifecycle.initial);
    assert(widget != null);
    assert(_parent == null);
2677
    assert(parent == null || parent._debugLifecycleState == _ElementLifecycle.active);
2678 2679
    assert(slot == null);
    assert(depth == null);
2680
    assert(!_active);
2681 2682 2683
    _parent = parent;
    _slot = newSlot;
    _depth = _parent != null ? _parent.depth + 1 : 1;
2684
    _active = true;
2685 2686
    if (parent != null) // Only assign ownership if the parent is non-null
      _owner = parent.owner;
2687 2688 2689 2690
    if (widget.key is GlobalKey) {
      final GlobalKey key = widget.key;
      key._register(this);
    }
2691
    _updateInheritance();
2692
    assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; }());
2693 2694
  }

2695 2696 2697 2698 2699 2700 2701
  /// 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.
2702
  @mustCallSuper
2703
  void update(covariant Widget newWidget) {
2704 2705 2706 2707 2708 2709 2710 2711 2712
    // 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));
2713
    _widget = newWidget;
2714 2715
  }

2716 2717 2718 2719 2720
  /// 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.
2721
  @protected
2722
  void updateSlotForChild(Element child, dynamic newSlot) {
2723
    assert(_debugLifecycleState == _ElementLifecycle.active);
2724 2725 2726 2727 2728 2729 2730 2731
    assert(child != null);
    assert(child._parent == this);
    void visit(Element element) {
      element._updateSlot(newSlot);
      if (element is! RenderObjectElement)
        element.visitChildren(visit);
    }
    visit(child);
2732 2733
  }

2734
  void _updateSlot(dynamic newSlot) {
2735
    assert(_debugLifecycleState == _ElementLifecycle.active);
2736 2737
    assert(widget != null);
    assert(_parent != null);
2738
    assert(_parent._debugLifecycleState == _ElementLifecycle.active);
2739
    assert(depth != null);
2740
    _slot = newSlot;
2741
  }
2742

2743
  void _updateDepth(int parentDepth) {
2744
    final int expectedDepth = parentDepth + 1;
2745 2746 2747
    if (_depth < expectedDepth) {
      _depth = expectedDepth;
      visitChildren((Element child) {
2748
        child._updateDepth(expectedDepth);
2749 2750 2751 2752
      });
    }
  }

2753 2754 2755
  /// Remove [renderObject] from the render tree.
  ///
  /// The default implementation of this function simply calls
2756
  /// [detachRenderObject] recursively on its child. The
2757 2758
  /// [RenderObjectElement.detachRenderObject] override does the actual work of
  /// removing [renderObject] from the render tree.
2759 2760
  ///
  /// This is called by [deactivateChild].
2761 2762 2763 2764 2765 2766 2767
  void detachRenderObject() {
    visitChildren((Element child) {
      child.detachRenderObject();
    });
    _slot = null;
  }

2768 2769 2770
  /// Add [renderObject] to the render tree at the location specified by [slot].
  ///
  /// The default implementation of this function simply calls
2771
  /// [attachRenderObject] recursively on its child. The
2772 2773
  /// [RenderObjectElement.attachRenderObject] override does the actual work of
  /// adding [renderObject] to the render tree.
2774 2775 2776 2777 2778 2779 2780 2781
  void attachRenderObject(dynamic newSlot) {
    assert(_slot == null);
    visitChildren((Element child) {
      child.attachRenderObject(newSlot);
    });
    _slot = newSlot;
  }

2782
  Element _retakeInactiveElement(GlobalKey key, Widget newWidget) {
2783 2784 2785 2786 2787 2788
    // 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.
2789
    final Element element = key._currentElement;
2790 2791
    if (element == null)
      return null;
2792
    if (!Widget.canUpdate(element.widget, newWidget))
2793
      return null;
2794 2795
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle)
2796
        debugPrint('Attempting to take $element from ${element._parent ?? "inactive elements list"} to put in $this.');
2797
      return true;
2798
    }());
2799 2800
    final Element parent = element._parent;
    if (parent != null) {
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816
      assert(() {
        if (parent == this) {
          throw new FlutterError(
            'A GlobalKey was used multiple times inside one widget\'s child list.\n'
            'The offending GlobalKey was: $key\n'
            'The parent of the widgets with that key was:\n  $parent\n'
            'The first child to get instantiated with that key became:\n  $element\n'
            'The second child that was to be instantiated with that key was:\n  $widget\n'
            'A GlobalKey can only be specified on one widget at a time in the widget tree.'
          );
        }
        parent.owner._debugTrackElementThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans(
          parent,
          key,
        );
        return true;
2817
      }());
2818
      parent.forgetChild(element);
2819
      parent.deactivateChild(element);
2820
    }
2821
    assert(element._parent == null);
2822
    owner._inactiveElements.remove(element);
2823 2824 2825
    return element;
  }

2826 2827
  /// Create an element for the given widget and add it as a child of this
  /// element in the given slot.
2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839
  ///
  /// 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.
2840
  @protected
Hixie's avatar
Hixie committed
2841
  Element inflateWidget(Widget newWidget, dynamic newSlot) {
2842
    assert(newWidget != null);
2843
    final Key key = newWidget.key;
2844
    if (key is GlobalKey) {
2845
      final Element newChild = _retakeInactiveElement(key, newWidget);
2846 2847
      if (newChild != null) {
        assert(newChild._parent == null);
2848
        assert(() { _debugCheckForCycles(newChild); return true; }());
2849
        newChild._activateWithParent(this, newSlot);
2850
        final Element updatedChild = updateChild(newChild, newWidget, newSlot);
2851 2852 2853 2854
        assert(newChild == updatedChild);
        return updatedChild;
      }
    }
2855
    final Element newChild = newWidget.createElement();
2856
    assert(() { _debugCheckForCycles(newChild); return true; }());
2857 2858 2859 2860 2861
    newChild.mount(this, newSlot);
    assert(newChild._debugLifecycleState == _ElementLifecycle.active);
    return newChild;
  }

2862 2863 2864 2865 2866 2867 2868 2869
  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;
2870
    }());
2871 2872
  }

2873 2874
  /// Move the given element to the list of inactive elements and detach its
  /// render object from the render tree.
2875 2876 2877 2878 2879
  ///
  /// 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.
  ///
2880 2881
  /// This method (indirectly) calls [deactivate] on the child.
  ///
2882
  /// The caller is responsible for removing the child from its child model.
2883 2884
  /// Typically [deactivateChild] is called by the element itself while it is
  /// updating its child model; however, during [GlobalKey] reparenting, the new
2885 2886
  /// parent proactively calls the old parent's [deactivateChild], first using
  /// [forgetChild] to cause the old parent to update its child model.
2887
  @protected
Hixie's avatar
Hixie committed
2888
  void deactivateChild(Element child) {
2889 2890 2891
    assert(child != null);
    assert(child._parent == this);
    child._parent = null;
2892
    child.detachRenderObject();
2893
    owner._inactiveElements.add(child); // this eventually calls child.deactivate()
2894 2895 2896 2897 2898 2899
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle) {
        if (child.widget.key is GlobalKey)
          debugPrint('Deactivated $child (keyed child of $this)');
      }
      return true;
2900
    }());
2901
  }
2902

2903 2904 2905 2906 2907 2908
  /// 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.
  ///
2909 2910
  /// 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.
2911 2912 2913
  @protected
  void forgetChild(Element child);

2914
  void _activateWithParent(Element parent, dynamic newSlot) {
2915 2916
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
    _parent = parent;
2917 2918 2919 2920
    assert(() {
      if (debugPrintGlobalKeyedWidgetLifecycle)
        debugPrint('Reactivating $this (now child of $_parent).');
      return true;
2921
    }());
2922 2923
    _updateDepth(_parent.depth);
    _activateRecursively(this);
2924 2925 2926 2927
    attachRenderObject(newSlot);
    assert(_debugLifecycleState == _ElementLifecycle.active);
  }

2928 2929 2930 2931 2932 2933 2934
  static void _activateRecursively(Element element) {
    assert(element._debugLifecycleState == _ElementLifecycle.inactive);
    element.activate();
    assert(element._debugLifecycleState == _ElementLifecycle.active);
    element.visitChildren(_activateRecursively);
  }

2935 2936 2937 2938 2939 2940 2941 2942
  /// 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.
2943
  @mustCallSuper
2944
  void activate() {
2945 2946
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
    assert(widget != null);
2947
    assert(owner != null);
2948 2949
    assert(depth != null);
    assert(!_active);
2950
    final bool hadDependencies = ((_dependencies != null && _dependencies.isNotEmpty) || _hadUnsatisfiedDependencies);
2951
    _active = true;
2952 2953 2954
    // 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();
2955
    _hadUnsatisfiedDependencies = false;
2956
    _updateInheritance();
2957
    assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; }());
2958 2959 2960
    if (_dirty)
      owner.scheduleBuildFor(this);
    if (hadDependencies)
2961
      didChangeDependencies();
2962 2963
  }

2964 2965 2966 2967 2968 2969 2970 2971 2972
  /// 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.
  ///
2973 2974
  /// This is (indirectly) called by [deactivateChild].
  ///
2975
  /// See the lifecycle documentation for [Element] for additional information.
2976
  @mustCallSuper
2977 2978 2979 2980
  void deactivate() {
    assert(_debugLifecycleState == _ElementLifecycle.active);
    assert(widget != null);
    assert(depth != null);
2981
    assert(_active);
2982
    if (_dependencies != null && _dependencies.isNotEmpty) {
2983
      for (InheritedElement dependency in _dependencies)
2984
        dependency._dependents.remove(this);
2985 2986 2987
      // 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
2988 2989 2990
      // 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.
2991
    }
2992
    _inheritedWidgets = null;
2993
    _active = false;
2994
    assert(() { _debugLifecycleState = _ElementLifecycle.inactive; return true; }());
2995 2996
  }

2997 2998 2999
  /// Called, in debug mode, after children have been deactivated (see [deactivate]).
  ///
  /// This method is not called in release builds.
3000
  @mustCallSuper
3001 3002 3003 3004
  void debugDeactivated() {
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
  }

3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
  /// 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.
3016
  @mustCallSuper
3017
  void unmount() {
3018
    assert(_debugLifecycleState == _ElementLifecycle.inactive);
3019 3020
    assert(widget != null);
    assert(depth != null);
3021
    assert(!_active);
3022 3023 3024 3025
    if (widget.key is GlobalKey) {
      final GlobalKey key = widget.key;
      key._unregister(this);
    }
3026
    assert(() { _debugLifecycleState = _ElementLifecycle.defunct; return true; }());
3027 3028
  }

3029
  @override
Hixie's avatar
Hixie committed
3030 3031
  RenderObject findRenderObject() => renderObject;

3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049
  @override
  Size get size {
    assert(() {
      if (_debugLifecycleState != _ElementLifecycle.active) {
        throw new FlutterError(
          'Cannot get size of inactive element.\n'
          'In order for an element to have a valid size, the element must be '
          'active, which means it is part of the tree. Instead, this element '
          'is in the $_debugLifecycleState state.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
        );
      }
      if (owner._debugBuilding) {
        throw new FlutterError(
          'Cannot get size during build.\n'
          'The size of this render object has not yet been determined because '
          'the framework is still in the process of building widgets, which '
3050
          'means the render tree for this frame has not yet been determined. '
3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064
          'The size getter should only be called from paint callbacks or '
          'interaction event handlers (e.g. gesture callbacks).\n'
          '\n'
          '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://docs.flutter.io/flutter/widgets/LayoutBuilder-class.html> '
          'for more details.\n'
          '\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
        );
      }
      return true;
3065
    }());
3066 3067 3068 3069 3070 3071
    final RenderObject renderObject = findRenderObject();
    assert(() {
      if (renderObject == null) {
        throw new FlutterError(
          'Cannot get size without a render object.\n'
          'In order for an element to have a valid size, the element must have '
3072
          'an assoicated render object. This element does not have an associated '
3073 3074 3075 3076 3077 3078 3079
          '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.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
        );
      }
3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090
      if (renderObject is RenderSliver) {
        throw new FlutterError(
          'Cannot get size from a RenderSliver.\n'
          '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.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
3091
          'The associated render sliver was:\n'
3092
          '  ${renderObject.toStringShallow(joiner: "\n  ")}'
3093 3094
        );
      }
3095 3096 3097 3098 3099 3100 3101 3102 3103
      if (renderObject is! RenderBox) {
        throw new FlutterError(
          'Cannot get size from a render object that is not a RenderBox.\n'
          '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.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
3104
          'The associated render object was:\n'
3105
          '  ${renderObject.toStringShallow(joiner: "\n  ")}'
3106 3107 3108
        );
      }
      final RenderBox box = renderObject;
3109
      if (!box.hasSize) {
3110 3111 3112 3113 3114
        throw new FlutterError(
          'Cannot get size from a render object that has not been through layout.\n'
          '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 '
3115
          '(e.g., during the build phase) before the framework has determined '
3116 3117 3118
          'the size and position of the render objects during layout.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
3119
          'The render object from which the size was to be obtained was:\n'
3120
          '  ${box.toStringShallow(joiner: "\n  ")}'
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133
        );
      }
      if (box.debugNeedsLayout) {
        throw new FlutterError(
          'Cannot get size from a render object that has been marked dirty for layout.\n'
          '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.\n'
          'The size getter was called for the following element:\n'
          '  $this\n'
          'The render object from which the size was to be obtained was:\n'
3134
          '  ${box.toStringShallow(joiner: "\n  ")}\n'
3135 3136
          'Consider using debugPrintMarkNeedsLayoutStacks to determine why the render '
          'object in question is dirty, if you did not expect this.'
3137 3138 3139
        );
      }
      return true;
3140
    }());
3141 3142 3143 3144 3145
    if (renderObject is RenderBox)
      return renderObject.size;
    return null;
  }

3146
  Map<Type, InheritedElement> _inheritedWidgets;
3147
  Set<InheritedElement> _dependencies;
3148
  bool _hadUnsatisfiedDependencies = false;
3149

3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161
  bool _debugCheckStateIsActiveForAncestorLoopkup() {
    assert(() {
      if (_debugLifecycleState != _ElementLifecycle.active) {
        throw new FlutterError(
          'Looking up a deactivated widget\'s ancestor is unsafe.\n'
          'At this point the state of the widget\'s element tree is no longer '
          'stable. To safely refer to a widget\'s ancestor in its dispose() method, '
          'save a reference to the ancestor by calling inheritFromWidgetOfExactType() '
          'in the widget\'s didChangeDependencies() method.\n'
        );
      }
      return true;
3162
    }());
3163 3164 3165
    return true;
  }

3166
  @override
Ian Hickson's avatar
Ian Hickson committed
3167
  InheritedWidget inheritFromWidgetOfExactType(Type targetType) {
3168
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
3169
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
3170 3171
    if (ancestor != null) {
      assert(ancestor is InheritedElement);
3172
      _dependencies ??= new HashSet<InheritedElement>();
3173
      _dependencies.add(ancestor);
3174
      ancestor._dependents.add(this);
3175 3176
      return ancestor.widget;
    }
3177
    _hadUnsatisfiedDependencies = true;
3178
    return null;
Hixie's avatar
Hixie committed
3179 3180
  }

Matt Perry's avatar
Matt Perry committed
3181 3182
  @override
  InheritedElement ancestorInheritedElementForWidgetOfExactType(Type targetType) {
3183
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
3184
    final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
Matt Perry's avatar
Matt Perry committed
3185 3186 3187
    return ancestor;
  }

3188
  void _updateInheritance() {
3189
    assert(_active);
3190 3191 3192
    _inheritedWidgets = _parent?._inheritedWidgets;
  }

3193
  @override
Ian Hickson's avatar
Ian Hickson committed
3194
  Widget ancestorWidgetOfExactType(Type targetType) {
3195
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
3196 3197 3198 3199
    Element ancestor = _parent;
    while (ancestor != null && ancestor.widget.runtimeType != targetType)
      ancestor = ancestor._parent;
    return ancestor?.widget;
3200 3201
  }

3202
  @override
Ian Hickson's avatar
Ian Hickson committed
3203
  State ancestorStateOfType(TypeMatcher matcher) {
3204
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
Hixie's avatar
Hixie committed
3205 3206
    Element ancestor = _parent;
    while (ancestor != null) {
3207
      if (ancestor is StatefulElement && matcher.check(ancestor.state))
Hixie's avatar
Hixie committed
3208 3209 3210
        break;
      ancestor = ancestor._parent;
    }
3211
    final StatefulElement statefulAncestor = ancestor;
Hixie's avatar
Hixie committed
3212 3213
    return statefulAncestor?.state;
  }
3214

3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227
  @override
  State rootAncestorStateOfType(TypeMatcher matcher) {
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
    Element ancestor = _parent;
    StatefulElement statefulAncestor;
    while (ancestor != null) {
      if (ancestor is StatefulElement && matcher.check(ancestor.state))
        statefulAncestor = ancestor;
      ancestor = ancestor._parent;
    }
    return statefulAncestor?.state;
  }

3228
  @override
Ian Hickson's avatar
Ian Hickson committed
3229
  RenderObject ancestorRenderObjectOfType(TypeMatcher matcher) {
3230
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
3231 3232
    Element ancestor = _parent;
    while (ancestor != null) {
Ian Hickson's avatar
Ian Hickson committed
3233
      if (ancestor is RenderObjectElement && matcher.check(ancestor.renderObject))
3234 3235 3236
        break;
      ancestor = ancestor._parent;
    }
3237
    final RenderObjectElement renderObjectAncestor = ancestor;
3238 3239 3240
    return renderObjectAncestor?.renderObject;
  }

3241
  @override
3242
  void visitAncestorElements(bool visitor(Element element)) {
3243
    assert(_debugCheckStateIsActiveForAncestorLoopkup());
3244 3245 3246
    Element ancestor = _parent;
    while (ancestor != null && visitor(ancestor))
      ancestor = ancestor._parent;
3247 3248
  }

3249 3250 3251 3252 3253 3254 3255 3256
  /// Called when a dependency of this element changes.
  ///
  /// The [inheritFromWidgetOfExactType] registers this element as depending on
  /// 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.
3257
  @mustCallSuper
3258 3259
  void didChangeDependencies() {
    assert(_active); // otherwise markNeedsBuild is a no-op
3260
    assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
3261 3262
    markNeedsBuild();
  }
3263

3264
  bool _debugCheckOwnerBuildTargetExists(String methodName) {
3265 3266 3267
    assert(() {
      if (owner._debugCurrentBuildTarget == null) {
        throw new FlutterError(
3268 3269 3270 3271 3272 3273 3274 3275 3276
          '$methodName for ${widget.runtimeType} was called at an '
          'inappropriate time.\n'
          'It may only be called while the widgets are being built. 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)'
3277 3278 3279
        );
      }
      return true;
3280 3281
    }());
    return true;
3282 3283
  }

3284 3285 3286
  /// Returns a description of what caused this element to be created.
  ///
  /// Useful for debugging the source of an element.
3287
  String debugGetCreatorChain(int limit) {
3288
    final List<String> chain = <String>[];
3289 3290 3291 3292 3293 3294 3295
    Element node = this;
    while (chain.length < limit && node != null) {
      chain.add(node.toStringShort());
      node = node._parent;
    }
    if (node != null)
      chain.add('\u22EF');
3296
    return chain.join(' \u2190 ');
3297 3298
  }

3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312
  /// 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;
  }

3313
  /// A short, textual description of this element.
3314
  @override String toStringShort() {
3315 3316 3317
    return widget != null ? '${widget.toStringShort()}' : '[$runtimeType]';
  }

3318 3319 3320 3321
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
    description.defaultDiagnosticsTreeStyle= DiagnosticsTreeStyle.dense;
3322 3323 3324
    description.add(new ObjectFlagProperty<int>('depth', depth, ifNull: 'no depth'));
    description.add(new ObjectFlagProperty<Widget>('widget', widget, ifNull: 'no widget'));
    if (widget != null) {
3325
      description.add(new DiagnosticsProperty<Key>('key', widget?.key, showName: false, defaultValue: null, level: DiagnosticLevel.hidden));
3326
      widget.debugFillProperties(description);
3327
    }
3328
    description.add(new FlagProperty('dirty', value: dirty, ifTrue: 'dirty'));
3329
  }
3330

3331
  @override
3332 3333 3334
  List<DiagnosticsNode> debugDescribeChildren() {
    final List<DiagnosticsNode> children = <DiagnosticsNode>[];
    visitChildren((Element child) {
3335 3336 3337 3338 3339
      if (child != null) {
        children.add(child.toDiagnosticsNode());
      } else {
        children.add(new DiagnosticsNode.message('<null child>'));
      }
3340 3341
    });
    return children;
3342
  }
3343

3344 3345 3346
  /// Returns true if the element has been marked as needing rebuilding.
  bool get dirty => _dirty;
  bool _dirty = true;
3347

3348 3349 3350 3351
  // 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;

3352 3353 3354
  // Whether we've already built or not. Set in [rebuild].
  bool _debugBuiltOnce = false;

3355
  // We let widget authors call setState from initState, didUpdateWidget, and
3356 3357
  // 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
3358
  // currently undergoing initState, didUpdateWidget, or build.
3359 3360 3361 3362
  bool _debugAllowIgnoredCallsToMarkNeedsBuild = false;
  bool _debugSetAllowIgnoredCallsToMarkNeedsBuild(bool value) {
    assert(_debugAllowIgnoredCallsToMarkNeedsBuild == !value);
    _debugAllowIgnoredCallsToMarkNeedsBuild = value;
3363 3364 3365
    return true;
  }

3366 3367 3368 3369
  /// 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,
3370 3371
  /// applications and widgets should be structured so as to only mark
  /// widgets dirty during event handlers before the frame begins, not during
3372 3373 3374
  /// the build itself.
  void markNeedsBuild() {
    assert(_debugLifecycleState != _ElementLifecycle.defunct);
3375 3376
    if (!_active)
      return;
3377
    assert(owner != null);
3378
    assert(_debugLifecycleState == _ElementLifecycle.active);
Hixie's avatar
Hixie committed
3379
    assert(() {
3380
      if (owner._debugBuilding) {
3381 3382
        assert(owner._debugCurrentBuildTarget != null);
        assert(owner._debugStateLocked);
3383
        if (_debugIsInScope(owner._debugCurrentBuildTarget))
Hixie's avatar
Hixie committed
3384
          return true;
3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402
        if (!_debugAllowIgnoredCallsToMarkNeedsBuild) {
          throw new FlutterError(
            'setState() or markNeedsBuild() called during build.\n'
            '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.\n'
            'The widget on which setState() or markNeedsBuild() was called was:\n'
            '  $this\n'
            '${owner._debugCurrentBuildTarget == null ? "" : "The widget which was currently being built when the offending call was made was:\n  ${owner._debugCurrentBuildTarget}"}'
          );
        }
        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);
3403
        throw new FlutterError(
3404 3405 3406 3407 3408
          'setState() or markNeedsBuild() called when widget tree was locked.\n'
          'This ${widget.runtimeType} widget cannot be marked as needing to build '
          'because the framework is locked.\n'
          'The widget on which setState() or markNeedsBuild() was called was:\n'
          '  $this\n'
3409 3410 3411
        );
      }
      return true;
3412
    }());
3413 3414 3415
    if (dirty)
      return;
    _dirty = true;
3416
    owner.scheduleBuildFor(this);
3417
  }
3418

3419 3420 3421
  /// 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.
3422 3423
  void rebuild() {
    assert(_debugLifecycleState != _ElementLifecycle.initial);
3424
    if (!_active || !_dirty)
3425
      return;
3426
    assert(() {
3427 3428 3429 3430 3431 3432 3433 3434
      if (debugPrintRebuildDirtyWidgets) {
        if (!_debugBuiltOnce) {
          debugPrint('Building $this');
          _debugBuiltOnce = true;
        } else {
          debugPrint('Rebuilding $this');
        }
      }
3435
      return true;
3436
    }());
3437
    assert(_debugLifecycleState == _ElementLifecycle.active);
3438
    assert(owner._debugStateLocked);
3439
    Element debugPreviousBuildTarget;
3440
    assert(() {
3441 3442
      debugPreviousBuildTarget = owner._debugCurrentBuildTarget;
      owner._debugCurrentBuildTarget = this;
3443
      return true;
3444
    }());
3445 3446
    performRebuild();
    assert(() {
3447 3448
      assert(owner._debugCurrentBuildTarget == this);
      owner._debugCurrentBuildTarget = debugPreviousBuildTarget;
3449
      return true;
3450
    }());
3451
    assert(!_dirty);
3452 3453
  }

3454
  /// Called by rebuild() after the appropriate checks have been made.
3455
  @protected
3456
  void performRebuild();
3457
}
3458

3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472
/// 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.
typedef Widget ErrorWidgetBuilder(FlutterErrorDetails details);

3473 3474
/// A widget that renders an exception's message.
///
3475
/// This widget is used when a build method fails, to help with determining
3476 3477 3478 3479 3480 3481 3482
/// 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.
class ErrorWidget extends LeafRenderObjectWidget {
  /// Creates a widget that displays the given error message.
  ErrorWidget(Object exception) : message = _stringify(exception),
      super(key: new UniqueKey());
3483

3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509
  /// 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].
  ///
  /// 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.
  static ErrorWidgetBuilder builder = (FlutterErrorDetails details) => new ErrorWidget(details.exception);

3510 3511 3512 3513 3514 3515
  /// The message to display.
  final String message;

  static String _stringify(Object exception) {
    try {
      return exception.toString();
3516
    } catch (e) { } // ignore: empty_catches
3517
    return 'Error';
3518 3519
  }

3520
  @override
3521
  RenderBox createRenderObject(BuildContext context) => new RenderErrorBox(message);
3522

3523
  @override
3524
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
3525 3526
    super.debugFillProperties(description);
    description.add(new StringProperty('message', message, quoted: false));
3527
  }
3528 3529
}

3530 3531 3532 3533
/// Signature for a function that creates a widget, e.g. [StatelessWidget.build]
/// or [State.build].
///
/// Used by [Builder.builder], [OverlayEntry.builder], etc.
3534
typedef Widget WidgetBuilder(BuildContext context);
3535

3536 3537 3538
/// Signature for a function that creates a widget for a given index, e.g., in a
/// list.
///
3539
/// Used by [ListView.builder] and other APIs that use lazily-generated widgets.
3540
typedef Widget IndexedWidgetBuilder(BuildContext context, int index);
3541

3542 3543 3544 3545
/// An [Element] that composes other [Element]s.
///
/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
/// [RenderObject]s indirectly by creating other [Element]s.
3546 3547
///
/// Contrast with [RenderObjectElement].
3548
abstract class ComponentElement extends Element {
3549
  /// Creates an element that uses the given widget as its configuration.
3550
  ComponentElement(Widget widget) : super(widget);
3551 3552 3553

  Element _child;

3554
  @override
3555 3556 3557 3558
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    assert(_child == null);
    assert(_active);
Ian Hickson's avatar
Ian Hickson committed
3559
    _firstBuild();
3560 3561 3562
    assert(_child != null);
  }

Ian Hickson's avatar
Ian Hickson committed
3563 3564 3565 3566
  void _firstBuild() {
    rebuild();
  }

3567 3568 3569
  /// 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.
3570
  ///
3571 3572
  /// Called automatically during [mount] to generate the first build, and by
  /// [rebuild] when the element needs updating.
3573
  @override
3574
  void performRebuild() {
3575 3576 3577 3578
    assert(() {
      if (debugProfileBuildsEnabled)
        Timeline.startSync('${widget.runtimeType}');
      return true;
3579
    }());
3580

3581 3582 3583
    assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
    Widget built;
    try {
3584
      built = build();
3585
      debugWidgetBuilderValue(widget, built);
3586
    } catch (e, stack) {
3587
      built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
3588
    } finally {
3589
      // We delay marking the element as clean until after calling build() so
3590 3591 3592 3593 3594 3595 3596 3597
      // 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) {
3598
      built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
3599 3600
      _child = updateChild(null, built, slot);
    }
3601 3602 3603 3604 3605

    assert(() {
      if (debugProfileBuildsEnabled)
        Timeline.finishSync();
      return true;
3606
    }());
3607 3608
  }

3609 3610 3611
  /// Subclasses should override this function to actually call the appropriate
  /// `build` function (e.g., [StatelessWidget.build] or [State.build]) for
  /// their widget.
3612 3613 3614
  @protected
  Widget build();

3615
  @override
3616 3617 3618 3619 3620
  void visitChildren(ElementVisitor visitor) {
    if (_child != null)
      visitor(_child);
  }

3621
  @override
3622
  void forgetChild(Element child) {
3623 3624 3625 3626 3627
    assert(child == _child);
    _child = null;
  }
}

3628
/// An [Element] that uses a [StatelessWidget] as its configuration.
3629
class StatelessElement extends ComponentElement {
3630
  /// Creates an element that uses the given widget as its configuration.
3631
  StatelessElement(StatelessWidget widget) : super(widget);
3632

3633
  @override
3634
  StatelessWidget get widget => super.widget;
3635

3636 3637 3638
  @override
  Widget build() => widget.build(this);

3639
  @override
3640
  void update(StatelessWidget newWidget) {
3641 3642 3643 3644 3645 3646
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}
3647

3648
/// An [Element] that uses a [StatefulWidget] as its configuration.
3649
class StatefulElement extends ComponentElement {
3650
  /// Creates an element that uses the given widget as its configuration.
3651
  StatefulElement(StatefulWidget widget)
3652
    : _state = widget.createState(), super(widget) {
3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
    assert(() {
      if (!_state._debugTypesAreRight(widget)) {
        throw new FlutterError(
          'StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>\n'
          '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.'
        );
      }
      return true;
3663
    }());
3664 3665
    assert(_state._element == null);
    _state._element = this;
3666 3667
    assert(_state._widget == null);
    _state._widget = widget;
3668
    assert(_state._debugLifecycleState == _StateLifecycle.created);
Ian Hickson's avatar
Ian Hickson committed
3669 3670
  }

3671 3672 3673
  @override
  Widget build() => state.build(this);

3674 3675 3676 3677 3678
  /// 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].
3679 3680
  State<StatefulWidget> get state => _state;
  State<StatefulWidget> _state;
Ian Hickson's avatar
Ian Hickson committed
3681

3682 3683
  @override
  void _reassemble() {
3684
    state.reassemble();
3685 3686 3687
    super._reassemble();
  }

3688
  @override
Ian Hickson's avatar
Ian Hickson committed
3689 3690
  void _firstBuild() {
    assert(_state._debugLifecycleState == _StateLifecycle.created);
3691
    try {
3692 3693
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
      _state.initState();
3694
    } finally {
3695
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
3696
    }
3697
    assert(() { _state._debugLifecycleState = _StateLifecycle.initialized; return true; }());
3698
    _state.didChangeDependencies();
3699
    assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; }());
Ian Hickson's avatar
Ian Hickson committed
3700
    super._firstBuild();
3701
  }
3702

3703
  @override
3704
  void update(StatefulWidget newWidget) {
3705 3706
    super.update(newWidget);
    assert(widget == newWidget);
3707 3708 3709
    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
3710 3711
    // asserts.
    _dirty = true;
3712
    _state._widget = widget;
3713 3714
    try {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
3715
      _state.didUpdateWidget(oldWidget);
3716 3717
    } finally {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
3718
    }
3719
    rebuild();
3720
  }
3721

3722 3723 3724
  @override
  void activate() {
    super.activate();
3725
    // Since the State could have observed the deactivate() and thus disposed of
3726
    // resources allocated in the build method, we have to rebuild the widget
3727 3728
    // so that its State can reallocate its resources.
    assert(_active); // otherwise markNeedsBuild is a no-op
3729 3730 3731
    markNeedsBuild();
  }

3732
  @override
3733 3734 3735 3736 3737
  void deactivate() {
    _state.deactivate();
    super.deactivate();
  }

3738
  @override
3739 3740 3741 3742 3743 3744
  void unmount() {
    super.unmount();
    _state.dispose();
    assert(() {
      if (_state._debugLifecycleState == _StateLifecycle.defunct)
        return true;
3745
      throw new FlutterError(
3746 3747 3748 3749
        '${_state.runtimeType}.dispose failed to call super.dispose.\n'
        'dispose() implementations must always call their superclass dispose() method, to ensure '
        'that all the resources used by the widget are fully released.'
      );
3750
    }());
3751 3752 3753
    _state._element = null;
    _state = null;
  }
3754

3755 3756 3757
  @override
  InheritedWidget inheritFromWidgetOfExactType(Type targetType) {
    assert(() {
3758 3759 3760 3761 3762 3763 3764 3765 3766
      if (state._debugLifecycleState == _StateLifecycle.created) {
        throw new FlutterError(
          'inheritFromWidgetOfExactType($targetType) was called before ${_state.runtimeType}.initState() completed.\n'
          'When an inherited widget changes, for example if the value of Theme.of() changes, '
          'its dependent widgets are rebuilt. If the dependent widget\'s reference to '
          '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.\n'
          'Typically references to to inherited widgets should occur in widget build() methods. Alternatively, '
3767
          'initialization based on inherited widgets can be placed in the didChangeDependencies method, which '
3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791
          'is called after initState and whenever the dependencies change thereafter.'
        );
      }
      if (state._debugLifecycleState == _StateLifecycle.defunct) {
        throw new FlutterError(
          'inheritFromWidgetOfExactType($targetType) called after dispose(): $this\n'
          'This error happens if you call inheritFromWidgetOfExactType() on the '
          '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 '
          'inheritFromWidgetOfExactType() from a timer or an animation callback. '
          '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 '
          'inheritFromWidgetOfExactType() to ensure the object is still in the '
          'tree.\n'
          'This error might indicate a memory leak if '
          'inheritFromWidgetOfExactType() 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().'
        );
      }
      return true;
3792
    }());
3793 3794 3795
    return super.inheritFromWidgetOfExactType(targetType);
  }

3796
  @override
3797 3798 3799
  void didChangeDependencies() {
    super.didChangeDependencies();
    _state.didChangeDependencies();
3800 3801
  }

3802
  @override
3803
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
3804 3805
    super.debugFillProperties(description);
    description.add(new DiagnosticsProperty<State<StatefulWidget>>('state', state, defaultValue: null));
3806
  }
3807 3808
}

3809
/// An [Element] that uses a [ProxyWidget] as its configuration.
3810
abstract class ProxyElement extends ComponentElement {
3811
  /// Initializes fields for subclasses.
3812
  ProxyElement(ProxyWidget widget) : super(widget);
Hixie's avatar
Hixie committed
3813

3814
  @override
3815
  ProxyWidget get widget => super.widget;
3816

3817
  @override
3818
  Widget build() => widget.child;
3819

3820
  @override
3821
  void update(ProxyWidget newWidget) {
3822
    final ProxyWidget oldWidget = widget;
Hixie's avatar
Hixie committed
3823 3824 3825 3826
    assert(widget != null);
    assert(widget != newWidget);
    super.update(newWidget);
    assert(widget == newWidget);
3827
    notifyClients(oldWidget);
Hixie's avatar
Hixie committed
3828 3829 3830 3831
    _dirty = true;
    rebuild();
  }

3832
  /// Notify other objects that the widget associated with this element has changed.
3833 3834 3835
  ///
  /// Called during [update] after changing the widget associated with this
  /// element but before rebuilding this element.
3836
  @protected
3837
  void notifyClients(covariant ProxyWidget oldWidget);
Hixie's avatar
Hixie committed
3838 3839
}

3840
/// An [Element] that uses a [ParentDataWidget] as its configuration.
3841
class ParentDataElement<T extends RenderObjectWidget> extends ProxyElement {
3842
  /// Creates an element that uses the given widget as its configuration.
3843 3844
  ParentDataElement(ParentDataWidget<T> widget) : super(widget);

3845
  @override
3846
  ParentDataWidget<T> get widget => super.widget;
3847

3848
  @override
3849 3850
  void mount(Element parent, dynamic slot) {
    assert(() {
3851
      final List<Widget> badAncestors = <Widget>[];
3852
      Element ancestor = parent;
3853
      while (ancestor != null) {
Hixie's avatar
Hixie committed
3854
        if (ancestor is ParentDataElement<RenderObjectWidget>) {
3855 3856 3857 3858 3859 3860
          badAncestors.add(ancestor.widget);
        } else if (ancestor is RenderObjectElement) {
          if (widget.debugIsValidAncestor(ancestor.widget))
            break;
          badAncestors.add(ancestor.widget);
        }
3861 3862
        ancestor = ancestor._parent;
      }
3863 3864
      if (ancestor != null && badAncestors.isEmpty)
        return true;
3865
      throw new FlutterError(
3866 3867
        'Incorrect use of ParentDataWidget.\n' +
        widget.debugDescribeInvalidAncestorChain(
3868
          description: '$this',
3869
          ownershipChain: parent.debugGetCreatorChain(10),
3870 3871 3872 3873
          foundValidAncestor: ancestor != null,
          badAncestors: badAncestors
        )
      );
3874
    }());
3875
    super.mount(parent, slot);
3876 3877
  }

3878 3879 3880 3881 3882 3883 3884 3885
  void _applyParentData(ParentDataWidget<T> widget) {
    void applyParentDataToChild(Element child) {
      if (child is RenderObjectElement) {
        child._updateParentData(widget);
      } else {
        assert(child is! ParentDataElement<RenderObjectWidget>);
        child.visitChildren(applyParentDataToChild);
      }
3886
    }
3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903
    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
3904
  ///    affect layout or paint, and the value to be applied could not be
3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926
  ///    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);
3927 3928
  }

3929
  @override
3930
  void notifyClients(ParentDataWidget<T> oldWidget) {
3931
    _applyParentData(widget);
3932 3933
  }
}
3934

3935
/// An [Element] that uses a [InheritedWidget] as its configuration.
3936
class InheritedElement extends ProxyElement {
3937
  /// Creates an element that uses the given widget as its configuration.
Hixie's avatar
Hixie committed
3938 3939
  InheritedElement(InheritedWidget widget) : super(widget);

3940
  @override
3941 3942
  InheritedWidget get widget => super.widget;

3943
  final Set<Element> _dependents = new HashSet<Element>();
3944

3945
  @override
3946
  void _updateInheritance() {
3947
    assert(_active);
3948 3949
    final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
    if (incomingWidgets != null)
3950
      _inheritedWidgets = new HashMap<Type, InheritedElement>.from(incomingWidgets);
3951
    else
3952
      _inheritedWidgets = new HashMap<Type, InheritedElement>();
3953 3954
    _inheritedWidgets[widget.runtimeType] = this;
  }
3955

3956
  @override
3957 3958
  void debugDeactivated() {
    assert(() {
3959
      assert(_dependents.isEmpty);
3960
      return true;
3961
    }());
3962 3963 3964
    super.debugDeactivated();
  }

3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975
  /// Calls [Element.didChangeDependencies] of all dependent elements, if
  /// [InheritedWidget.updateShouldNotify] returns true.
  ///
  /// Notifies all dependent elements that this inherited widget has changed.
  ///
  /// [InheritedElement] calls this function if the [widget]'s
  /// [InheritedWidget.updateShouldNotify] returns true.
  ///
  /// This method must 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.
3976
  @override
3977
  void notifyClients(InheritedWidget oldWidget) {
Hixie's avatar
Hixie committed
3978 3979
    if (!widget.updateShouldNotify(oldWidget))
      return;
3980
    assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
3981
    for (Element dependent in _dependents) {
3982 3983
      assert(() {
        // check that it really is our descendant
3984
        Element ancestor = dependent._parent;
3985 3986 3987
        while (ancestor != this && ancestor != null)
          ancestor = ancestor._parent;
        return ancestor == this;
3988
      }());
3989
      // check that it really depends on us
3990
      assert(dependent._dependencies.contains(this));
3991
      dependent.didChangeDependencies();
3992 3993
    }
  }
3994
}
3995

3996
/// An [Element] that uses a [RenderObjectWidget] as its configuration.
3997 3998 3999 4000 4001 4002
///
/// [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].
4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038
///
/// 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 {
///
4039 4040
///   @override
///   Foo get widget => super.widget;
4041
///
4042 4043
///   @override
///   RenderFoo get renderObject => super.renderObject;
4044
///
4045
///   // ...
4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069
/// }
/// ```
///
/// ### 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]
4070
/// method. This method should call [updateChild] for each child, passing in
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088
/// 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
4089
/// order can matter; for example, if two of the children use [PageStorage]'s
Ian Hickson's avatar
Ian Hickson committed
4090 4091
/// `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.
4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104
///
/// #### 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
4105
/// then the render object's [RenderObject.performLayout] method can call back
4106 4107
/// to the element to have it generate the widgets and call [updateChild]
/// accordingly.
4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131
///
/// 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
4132
/// [forgetChild] method will be called with a reference to the affected child
4133 4134
/// element.
///
4135
/// The [forgetChild] method of a [RenderObjectElement] subclass must remove the
4136 4137 4138 4139
/// 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
4140
/// track which elements were forgotten by storing them in a [Set], rather than
4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154
/// 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.
4155 4156 4157 4158 4159 4160 4161
///
/// ### 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].
4162
abstract class RenderObjectElement extends Element {
4163
  /// Creates an element that uses the given widget as its configuration.
4164 4165
  RenderObjectElement(RenderObjectWidget widget) : super(widget);

4166
  @override
4167
  RenderObjectWidget get widget => super.widget;
4168

4169
  /// The underlying [RenderObject] for this element.
4170
  @override
4171
  RenderObject get renderObject => _renderObject;
4172
  RenderObject _renderObject;
4173

4174
  RenderObjectElement _ancestorRenderObjectElement;
4175

4176 4177 4178 4179
  RenderObjectElement _findAncestorRenderObjectElement() {
    Element ancestor = _parent;
    while (ancestor != null && ancestor is! RenderObjectElement)
      ancestor = ancestor._parent;
4180 4181 4182
    return ancestor;
  }

Hixie's avatar
Hixie committed
4183
  ParentDataElement<RenderObjectWidget> _findAncestorParentDataElement() {
4184 4185
    Element ancestor = _parent;
    while (ancestor != null && ancestor is! RenderObjectElement) {
Hixie's avatar
Hixie committed
4186
      if (ancestor is ParentDataElement<RenderObjectWidget>)
4187 4188
        return ancestor;
      ancestor = ancestor._parent;
4189
    }
4190 4191 4192
    return null;
  }

4193
  @override
4194 4195
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
4196
    _renderObject = widget.createRenderObject(this);
4197
    assert(() { _debugUpdateRenderObjectOwner(); return true; }());
4198
    assert(_slot == newSlot);
4199
    attachRenderObject(newSlot);
4200
    _dirty = false;
4201 4202
  }

4203
  @override
4204
  void update(covariant RenderObjectWidget newWidget) {
4205 4206
    super.update(newWidget);
    assert(widget == newWidget);
4207
    assert(() { _debugUpdateRenderObjectOwner(); return true; }());
4208
    widget.updateRenderObject(this, renderObject);
4209 4210 4211
    _dirty = false;
  }

4212
  void _debugUpdateRenderObjectOwner() {
4213 4214 4215
    assert(() {
      _renderObject.debugCreator = new _DebugCreator(this);
      return true;
4216
    }());
4217 4218
  }

4219
  @override
4220
  void performRebuild() {
4221
    widget.updateRenderObject(this, renderObject);
4222 4223 4224
    _dirty = false;
  }

4225 4226
  /// Updates the children of this element to use new widgets.
  ///
4227 4228 4229
  /// 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.
4230 4231 4232
  ///
  /// During this function the `oldChildren` list must not be modified. If the
  /// caller wishes to remove elements from `oldChildren` re-entrantly while
4233
  /// this function is on the stack, the caller can supply a `forgottenChildren`
4234 4235
  /// argument, which can be modified while this function is on the stack.
  /// Whenever this function reads from `oldChildren`, this function first
4236
  /// checks whether the child is in `forgottenChildren`. If it is, the function
4237 4238
  /// acts as if the child was not in `oldChildren`.
  ///
4239
  /// This function is a convenience wrapper around [updateChild], which updates
4240 4241
  /// each individual child. When calling [updateChild], this function uses the
  /// previous element as the `newSlot` argument.
4242
  @protected
4243
  List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element> forgottenChildren }) {
4244
    assert(oldChildren != null);
4245
    assert(newWidgets != null);
4246

4247 4248
    Element replaceWithNullIfForgotten(Element child) {
      return forgottenChildren != null && forgottenChildren.contains(child) ? null : child;
4249 4250
    }

4251 4252 4253 4254
    // 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.
4255

4256
    // The cases it tries to optimize for are:
4257 4258 4259 4260 4261 4262 4263 4264
    //  - 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:
4265 4266 4267 4268 4269
    // 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
4270
    //    from beginning to end.
4271 4272 4273 4274
    // 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.
4275
    // 4. Walk the narrowed part of the new list forwards:
4276
    //     * Sync non-keyed items with null
4277
    //     * Sync keyed items with the source if it exists, else with null.
4278
    // 5. Walk the bottom of the list again, syncing the nodes.
4279 4280 4281
    // 6. Sync null with any items in the list of keys that are still
    //    mounted.

4282 4283
    int newChildrenTop = 0;
    int oldChildrenTop = 0;
4284 4285
    int newChildrenBottom = newWidgets.length - 1;
    int oldChildrenBottom = oldChildren.length - 1;
4286

4287
    final List<Element> newChildren = oldChildren.length == newWidgets.length ?
4288 4289 4290 4291 4292 4293
        oldChildren : new List<Element>(newWidgets.length);

    Element previousChild;

    // Update the top of the list.
    while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4294 4295
      final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
      final Widget newWidget = newWidgets[newChildrenTop];
4296 4297
      assert(oldChild == null || oldChild._debugLifecycleState == _ElementLifecycle.active);
      if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
4298
        break;
4299
      final Element newChild = updateChild(oldChild, newWidget, previousChild);
4300 4301 4302 4303 4304
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
      oldChildrenTop += 1;
4305 4306
    }

4307 4308
    // Scan the bottom of the list.
    while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
4309 4310
      final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenBottom]);
      final Widget newWidget = newWidgets[newChildrenBottom];
4311 4312
      assert(oldChild == null || oldChild._debugLifecycleState == _ElementLifecycle.active);
      if (oldChild == null || !Widget.canUpdate(oldChild.widget, newWidget))
4313
        break;
4314 4315
      oldChildrenBottom -= 1;
      newChildrenBottom -= 1;
4316 4317
    }

4318
    // Scan the old children in the middle of the list.
4319
    final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
4320
    Map<Key, Element> oldKeyedChildren;
4321
    if (haveOldChildren) {
4322
      oldKeyedChildren = <Key, Element>{};
4323
      while (oldChildrenTop <= oldChildrenBottom) {
4324
        final Element oldChild = replaceWithNullIfForgotten(oldChildren[oldChildrenTop]);
4325 4326 4327 4328 4329
        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
4330
            deactivateChild(oldChild);
4331
        }
4332
        oldChildrenTop += 1;
4333
      }
4334 4335
    }

4336 4337
    // Update the middle of the list.
    while (newChildrenTop <= newChildrenBottom) {
4338
      Element oldChild;
4339
      final Widget newWidget = newWidgets[newChildrenTop];
4340
      if (haveOldChildren) {
4341
        final Key key = newWidget.key;
4342
        if (key != null) {
4343
          oldChild = oldKeyedChildren[key];
4344
          if (oldChild != null) {
4345
            if (Widget.canUpdate(oldChild.widget, newWidget)) {
4346 4347 4348 4349
              // we found a match!
              // remove it from oldKeyedChildren so we don't unsync it later
              oldKeyedChildren.remove(key);
            } else {
4350
              // Not a match, let's pretend we didn't see it for now.
4351
              oldChild = null;
4352
            }
4353 4354
          }
        }
4355
      }
4356
      assert(oldChild == null || Widget.canUpdate(oldChild.widget, newWidget));
4357
      final Element newChild = updateChild(oldChild, newWidget, previousChild);
4358 4359
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
4360 4361 4362
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
4363
    }
4364

4365
    // We've scanned the whole list.
4366 4367 4368 4369 4370 4371 4372 4373
    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)) {
4374
      final Element oldChild = oldChildren[oldChildrenTop];
4375
      assert(replaceWithNullIfForgotten(oldChild) != null);
4376
      assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
4377
      final Widget newWidget = newWidgets[newChildrenTop];
4378
      assert(Widget.canUpdate(oldChild.widget, newWidget));
4379
      final Element newChild = updateChild(oldChild, newWidget, previousChild);
4380 4381
      assert(newChild._debugLifecycleState == _ElementLifecycle.active);
      assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
4382 4383 4384 4385
      newChildren[newChildrenTop] = newChild;
      previousChild = newChild;
      newChildrenTop += 1;
      oldChildrenTop += 1;
4386 4387
    }

4388
    // Clean up any of the remaining middle nodes from the old list.
Ian Hickson's avatar
Ian Hickson committed
4389
    if (haveOldChildren && oldKeyedChildren.isNotEmpty) {
4390
      for (Element oldChild in oldKeyedChildren.values) {
4391
        if (forgottenChildren == null || !forgottenChildren.contains(oldChild))
Hixie's avatar
Hixie committed
4392
          deactivateChild(oldChild);
4393
      }
4394 4395
    }

4396
    return newChildren;
4397 4398
  }

4399
  @override
4400 4401 4402 4403 4404
  void deactivate() {
    super.deactivate();
    assert(!renderObject.attached);
  }

4405
  @override
4406 4407 4408 4409 4410 4411
  void unmount() {
    super.unmount();
    assert(!renderObject.attached);
    widget.didUnmountRenderObject(renderObject);
  }

4412
  void _updateParentData(ParentDataWidget<RenderObjectWidget> parentData) {
4413
    parentData.applyParentData(renderObject);
Hixie's avatar
Hixie committed
4414 4415
  }

4416
  @override
4417 4418 4419 4420 4421
  void _updateSlot(dynamic newSlot) {
    assert(slot != newSlot);
    super._updateSlot(newSlot);
    assert(slot == newSlot);
    _ancestorRenderObjectElement.moveChildRenderObject(renderObject, slot);
Hixie's avatar
Hixie committed
4422 4423
  }

4424
  @override
4425 4426 4427 4428 4429
  void attachRenderObject(dynamic newSlot) {
    assert(_ancestorRenderObjectElement == null);
    _slot = newSlot;
    _ancestorRenderObjectElement = _findAncestorRenderObjectElement();
    _ancestorRenderObjectElement?.insertChildRenderObject(renderObject, newSlot);
4430
    final ParentDataElement<RenderObjectWidget> parentDataElement = _findAncestorParentDataElement();
4431
    if (parentDataElement != null)
4432
      _updateParentData(parentDataElement.widget);
4433 4434
  }

4435
  @override
Hixie's avatar
Hixie committed
4436
  void detachRenderObject() {
4437 4438 4439 4440
    if (_ancestorRenderObjectElement != null) {
      _ancestorRenderObjectElement.removeChildRenderObject(renderObject);
      _ancestorRenderObjectElement = null;
    }
4441
    _slot = null;
Hixie's avatar
Hixie committed
4442 4443
  }

4444 4445 4446 4447 4448 4449
  /// Insert the given child into [renderObject] at the given slot.
  ///
  /// 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
  /// element has a list of children, the previous sibling is a convenient value
  /// for the slot.
4450
  @protected
4451
  void insertChildRenderObject(covariant RenderObject child, covariant dynamic slot);
4452

4453 4454 4455 4456 4457 4458 4459 4460
  /// Move the given child to the given slot.
  ///
  /// The given child is guaranteed to have [renderObject] as its parent.
  ///
  /// 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
  /// element has a list of children, the previous sibling is a convenient value
  /// for the slot.
4461
  @protected
4462
  void moveChildRenderObject(covariant RenderObject child, covariant dynamic slot);
4463

4464 4465 4466
  /// Remove the given child from [renderObject].
  ///
  /// The given child is guaranteed to have [renderObject] as its parent.
4467
  @protected
4468
  void removeChildRenderObject(covariant RenderObject child);
Hixie's avatar
Hixie committed
4469

4470
  @override
4471
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
4472 4473
    super.debugFillProperties(description);
    description.add(new DiagnosticsProperty<RenderObject>('renderObject', renderObject, defaultValue: null));
4474 4475
  }
}
Hixie's avatar
Hixie committed
4476

4477
/// The element at the root of the tree.
4478 4479 4480 4481
///
/// Only root elements may have their owner set explicitly. All other
/// elements inherit their owner from their parent.
abstract class RootRenderObjectElement extends RenderObjectElement {
4482
  /// Initializes fields for subclasses.
4483 4484
  RootRenderObjectElement(RenderObjectWidget widget): super(widget);

4485 4486 4487 4488 4489 4490 4491 4492
  /// 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
4493
  /// calling the build owner's [BuildOwner.buildScope] method. See
4494
  /// [WidgetsBinding.drawFrame].
4495 4496 4497 4498 4499 4500
  void assignOwner(BuildOwner owner) {
    _owner = owner;
  }

  @override
  void mount(Element parent, dynamic newSlot) {
4501
    // Root elements should never have parents.
4502 4503 4504 4505 4506 4507
    assert(parent == null);
    assert(newSlot == null);
    super.mount(parent, newSlot);
  }
}

4508
/// An [Element] that uses a [LeafRenderObjectWidget] as its configuration.
4509
class LeafRenderObjectElement extends RenderObjectElement {
4510
  /// Creates an element that uses the given widget as its configuration.
4511
  LeafRenderObjectElement(LeafRenderObjectWidget widget): super(widget);
Hixie's avatar
Hixie committed
4512

4513
  @override
4514
  void forgetChild(Element child) {
4515 4516 4517
    assert(false);
  }

4518
  @override
4519
  void insertChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
4520 4521 4522
    assert(false);
  }

4523
  @override
4524
  void moveChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
4525 4526 4527
    assert(false);
  }

4528
  @override
4529 4530 4531
  void removeChildRenderObject(RenderObject child) {
    assert(false);
  }
4532 4533 4534 4535 4536

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

4539
/// An [Element] that uses a [SingleChildRenderObjectWidget] as its configuration.
4540 4541 4542 4543 4544 4545
///
/// 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].
4546
class SingleChildRenderObjectElement extends RenderObjectElement {
4547
  /// Creates an element that uses the given widget as its configuration.
4548
  SingleChildRenderObjectElement(SingleChildRenderObjectWidget widget) : super(widget);
4549

4550
  @override
4551
  SingleChildRenderObjectWidget get widget => super.widget;
Hixie's avatar
Hixie committed
4552

4553
  Element _child;
Hixie's avatar
Hixie committed
4554

4555
  @override
4556 4557 4558
  void visitChildren(ElementVisitor visitor) {
    if (_child != null)
      visitor(_child);
Hixie's avatar
Hixie committed
4559 4560
  }

4561
  @override
4562
  void forgetChild(Element child) {
4563 4564 4565 4566
    assert(child == _child);
    _child = null;
  }

4567
  @override
4568 4569 4570
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _child = updateChild(_child, widget.child, null);
4571 4572
  }

4573
  @override
4574
  void update(SingleChildRenderObjectWidget newWidget) {
4575 4576 4577
    super.update(newWidget);
    assert(widget == newWidget);
    _child = updateChild(_child, widget.child, null);
Hixie's avatar
Hixie committed
4578 4579
  }

4580
  @override
4581
  void insertChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
4582
    final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject;
Hixie's avatar
Hixie committed
4583
    assert(slot == null);
4584
    assert(renderObject.debugValidateChild(child));
4585
    renderObject.child = child;
Hixie's avatar
Hixie committed
4586
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
4587 4588
  }

4589
  @override
4590 4591 4592 4593
  void moveChildRenderObject(RenderObject child, dynamic slot) {
    assert(false);
  }

4594
  @override
4595
  void removeChildRenderObject(RenderObject child) {
Hixie's avatar
Hixie committed
4596
    final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject;
4597
    assert(renderObject.child == child);
Hixie's avatar
Hixie committed
4598
    renderObject.child = null;
Hixie's avatar
Hixie committed
4599
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
4600 4601 4602
  }
}

4603
/// An [Element] that uses a [MultiChildRenderObjectWidget] as its configuration.
4604 4605 4606 4607 4608
///
/// 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].
4609
class MultiChildRenderObjectElement extends RenderObjectElement {
4610
  /// Creates an element that uses the given widget as its configuration.
4611 4612 4613
  MultiChildRenderObjectElement(MultiChildRenderObjectWidget widget)
    : assert(!debugChildrenHaveDuplicateKeys(widget, widget.children)),
      super(widget);
Hixie's avatar
Hixie committed
4614

4615
  @override
4616 4617
  MultiChildRenderObjectWidget get widget => super.widget;

4618 4619 4620 4621 4622 4623 4624
  /// The current list of children of this element.
  ///
  /// This list is filtered to hide elements that have been forgotten (using
  /// [forgetChild]).
  @protected
  Iterable<Element> get children => _children.where((Element child) => !_forgottenChildren.contains(child));

4625
  List<Element> _children;
4626
  // We keep a set of forgotten children to avoid O(n^2) work walking _children
4627
  // repeatedly to remove children.
4628
  final Set<Element> _forgottenChildren = new HashSet<Element>();
Hixie's avatar
Hixie committed
4629

4630
  @override
4631
  void insertChildRenderObject(RenderObject child, Element slot) {
Hixie's avatar
Hixie committed
4632
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject = this.renderObject;
4633
    assert(renderObject.debugValidateChild(child));
4634
    renderObject.insert(child, after: slot?.renderObject);
Hixie's avatar
Hixie committed
4635
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
4636 4637
  }

4638
  @override
4639
  void moveChildRenderObject(RenderObject child, dynamic slot) {
Hixie's avatar
Hixie committed
4640
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject = this.renderObject;
4641
    assert(child.parent == renderObject);
4642
    renderObject.move(child, after: slot?.renderObject);
Hixie's avatar
Hixie committed
4643
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
4644 4645
  }

4646
  @override
4647
  void removeChildRenderObject(RenderObject child) {
Hixie's avatar
Hixie committed
4648
    final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject = this.renderObject;
4649 4650
    assert(child.parent == renderObject);
    renderObject.remove(child);
Hixie's avatar
Hixie committed
4651
    assert(renderObject == this.renderObject);
Hixie's avatar
Hixie committed
4652 4653
  }

4654
  @override
4655
  void visitChildren(ElementVisitor visitor) {
4656
    for (Element child in _children) {
4657
      if (!_forgottenChildren.contains(child))
4658 4659 4660 4661
        visitor(child);
    }
  }

4662
  @override
4663
  void forgetChild(Element child) {
4664
    assert(_children.contains(child));
4665 4666
    assert(!_forgottenChildren.contains(child));
    _forgottenChildren.add(child);
4667 4668
  }

4669
  @override
4670 4671 4672 4673
  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    _children = new List<Element>(widget.children.length);
    Element previousChild;
4674 4675
    for (int i = 0; i < _children.length; i += 1) {
      final Element newChild = inflateWidget(widget.children[i], previousChild);
4676 4677
      _children[i] = newChild;
      previousChild = newChild;
4678 4679 4680
    }
  }

4681
  @override
4682
  void update(MultiChildRenderObjectWidget newWidget) {
4683 4684
    super.update(newWidget);
    assert(widget == newWidget);
4685 4686
    _children = updateChildren(_children, widget.children, forgottenChildren: _forgottenChildren);
    _forgottenChildren.clear();
4687
  }
4688 4689
}

4690 4691 4692 4693 4694 4695 4696
class _DebugCreator {
  _DebugCreator(this.element);
  final RenderObjectElement element;
  @override
  String toString() => element.debugGetCreatorChain(12);
}

4697 4698 4699 4700
FlutterErrorDetails _debugReportException(
  String context,
  dynamic exception,
  StackTrace stack, {
Ian Hickson's avatar
Ian Hickson committed
4701 4702
  InformationCollector informationCollector
}) {
4703
  final FlutterErrorDetails details = new FlutterErrorDetails(
4704 4705 4706
    exception: exception,
    stack: stack,
    library: 'widgets library',
Ian Hickson's avatar
Ian Hickson committed
4707 4708
    context: context,
    informationCollector: informationCollector,
4709 4710 4711
  );
  FlutterError.reportError(details);
  return details;
4712
}