Commit e8c9797d authored by Ian Hickson's avatar Ian Hickson Committed by GitHub
parent 8e64624a
...@@ -68,6 +68,19 @@ class ChangeNotifier extends Listenable { ...@@ -68,6 +68,19 @@ class ChangeNotifier extends Listenable {
/// If the given listener is not registered, the call is ignored. /// If the given listener is not registered, the call is ignored.
/// ///
/// This method must not be called after [dispose] has been called. /// This method must not be called after [dispose] has been called.
///
/// If a listener had been added twice, and is removed once during an
/// iteration (i.e. in response to a notification), it will still be called
/// again. If, on the other hand, it is removed as many times as it was
/// registered, then it will no longer be called. This odd behavior is the
/// result of the [ChangeNotifier] not being able to determine which listener
/// is being removed, since they are identical, and therefore conservatively
/// still calling all the listeners when it knows that any are still
/// registered.
///
/// This surprising behavior can be unexpectedly observed when registering a
/// listener on two separate objects which are both forwarding all
/// registrations to a common upstream object.
@override @override
void removeListener(VoidCallback listener) { void removeListener(VoidCallback listener) {
assert(_debugAssertNotDisposed); assert(_debugAssertNotDisposed);
...@@ -97,6 +110,10 @@ class ChangeNotifier extends Listenable { ...@@ -97,6 +110,10 @@ class ChangeNotifier extends Listenable {
/// [FlutterError.reportError]. /// [FlutterError.reportError].
/// ///
/// This method must not be called after [dispose] has been called. /// This method must not be called after [dispose] has been called.
///
/// Surprising behavior can result when reentrantly removing a listener (i.e.
/// in response to a notification) that has been registered multiple times.
/// See the discussion at [removeListener].
@protected @protected
void notifyListeners() { void notifyListeners() {
assert(_debugAssertNotDisposed); assert(_debugAssertNotDisposed);
......
...@@ -21,6 +21,11 @@ import 'theme.dart'; ...@@ -21,6 +21,11 @@ import 'theme.dart';
/// corners. Avoid using flat buttons where they would blend in with other /// corners. Avoid using flat buttons where they would blend in with other
/// content, for example in the middle of lists. /// content, for example in the middle of lists.
/// ///
/// Material design flat buttons have an all-caps label, some internal padding,
/// and some defined dimensions. To have a part of your application be
/// interactive, with ink splashes, without also committing to these stylistic
/// choices, consider using [InkWell] instead.
///
/// If the [onPressed] callback is null, then the button will be disabled, /// If the [onPressed] callback is null, then the button will be disabled,
/// will not react to touch, and will be colored as specified by /// will not react to touch, and will be colored as specified by
/// the [disabledColor] property instead of the [color] property. If you are /// the [disabledColor] property instead of the [color] property. If you are
...@@ -35,6 +40,7 @@ import 'theme.dart'; ...@@ -35,6 +40,7 @@ import 'theme.dart';
/// material. /// material.
/// * [DropdownButton], which offers the user a choice of a number of options. /// * [DropdownButton], which offers the user a choice of a number of options.
/// * [SimpleDialogOption], which is used in [SimpleDialog]s. /// * [SimpleDialogOption], which is used in [SimpleDialog]s.
/// * [InkWell], which implements the ink splash part of a flat button.
/// * <https://material.google.com/components/buttons.html> /// * <https://material.google.com/components/buttons.html>
class FlatButton extends StatelessWidget { class FlatButton extends StatelessWidget {
/// Creates a flat button. /// Creates a flat button.
......
...@@ -21,6 +21,11 @@ import 'theme.dart'; ...@@ -21,6 +21,11 @@ import 'theme.dart';
/// is true then the overall height of this list item and the size of the /// is true then the overall height of this list item and the size of the
/// [DefaultTextStyle]s that wrap the [title] and [subtitle] widget are reduced. /// [DefaultTextStyle]s that wrap the [title] and [subtitle] widget are reduced.
/// ///
/// List items are always a fixed height (which height depends on how
/// [isThreeLine], [dense], and [subtitle] are configured); they do not grow in
/// height based on their contents. If you are looking for a widget that allows
/// for arbitrary layout in a row, consider [Row].
///
/// List items are typically used in [MaterialList]s or in [Card]s. /// List items are typically used in [MaterialList]s or in [Card]s.
/// ///
/// Requires one of its ancestors to be a [Material] widget. /// Requires one of its ancestors to be a [Material] widget.
...@@ -84,7 +89,7 @@ class ListItem extends StatelessWidget { ...@@ -84,7 +89,7 @@ class ListItem extends StatelessWidget {
/// Whether this list item is interactive. /// Whether this list item is interactive.
/// ///
/// If `false`, this list item is styled with the disabled color from the /// If false, this list item is styled with the disabled color from the
/// current [Theme] and the [onTap] and [onLongPress] callbacks are /// current [Theme] and the [onTap] and [onLongPress] callbacks are
/// inoperative. /// inoperative.
final bool enabled; final bool enabled;
......
...@@ -59,7 +59,7 @@ class TwoLevelListItem extends StatelessWidget { ...@@ -59,7 +59,7 @@ class TwoLevelListItem extends StatelessWidget {
/// Whether this list item is interactive. /// Whether this list item is interactive.
/// ///
/// If `false`, this list item is styled with the disabled color from the /// If false, this list item is styled with the disabled color from the
/// current [Theme] and the [onTap] and [onLongPress] callbacks are /// current [Theme] and the [onTap] and [onLongPress] callbacks are
/// inoperative. /// inoperative.
final bool enabled; final bool enabled;
...@@ -128,7 +128,7 @@ class TwoLevelSublist extends StatefulWidget { ...@@ -128,7 +128,7 @@ class TwoLevelSublist extends StatefulWidget {
/// ///
/// When the sublist starts expanding, this function is called with the value /// When the sublist starts expanding, this function is called with the value
/// `true`. When the sublist starts collapsing, this function is called with /// `true`. When the sublist starts collapsing, this function is called with
/// the value `false`. /// the value false.
final ValueChanged<bool> onOpenChanged; final ValueChanged<bool> onOpenChanged;
/// The widgets that are displayed when the sublist expands. /// The widgets that are displayed when the sublist expands.
......
...@@ -540,7 +540,7 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> { ...@@ -540,7 +540,7 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
/// ///
/// If the new delegate is the same class as the previous one, then the new /// If the new delegate is the same class as the previous one, then the new
/// delegate has its [GridDelegate.shouldRelayout] called; if the result is /// delegate has its [GridDelegate.shouldRelayout] called; if the result is
/// `true`, then the delegate will be called. /// true, then the delegate will be called.
/// ///
/// If the new delegate is a different class than the previous one, then the /// If the new delegate is a different class than the previous one, then the
/// delegate will be called. /// delegate will be called.
......
...@@ -55,7 +55,7 @@ enum PerformanceOverlayOption { ...@@ -55,7 +55,7 @@ enum PerformanceOverlayOption {
/// ///
/// The simplest way to show the performance overlay is to set /// The simplest way to show the performance overlay is to set
/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]
/// to `true`. /// to true.
class RenderPerformanceOverlay extends RenderBox { class RenderPerformanceOverlay extends RenderBox {
/// Creates a performance overlay render object. /// Creates a performance overlay render object.
/// ///
......
...@@ -909,15 +909,15 @@ abstract class CustomClipper<T> { ...@@ -909,15 +909,15 @@ abstract class CustomClipper<T> {
/// the same thing, because the latter is implemented in terms of the former). /// the same thing, because the latter is implemented in terms of the former).
/// ///
/// If the new instance represents different information than the old /// If the new instance represents different information than the old
/// instance, then the method should return `true`, otherwise it should return /// instance, then the method should return true, otherwise it should return
/// `false`. /// false.
/// ///
/// If the method returns `false`, then the [getClip] call might be optimized /// If the method returns false, then the [getClip] call might be optimized
/// away. /// away.
/// ///
/// It's possible that the [getClip] method will get called even if /// It's possible that the [getClip] method will get called even if
/// [shouldReclip] returns `false` or if the [getClip] method is never called /// [shouldReclip] returns false or if the [shouldReclip] method is never
/// at all (e.g. if the box changes size). /// called at all (e.g. if the box changes size).
bool shouldReclip(@checked CustomClipper<T> oldClipper); bool shouldReclip(@checked CustomClipper<T> oldClipper);
} }
...@@ -1361,8 +1361,8 @@ class RenderTransform extends RenderProxyBox { ...@@ -1361,8 +1361,8 @@ class RenderTransform extends RenderProxyBox {
markNeedsPaint(); markNeedsPaint();
} }
/// When set to `true`, hit tests are performed based on the position of the /// When set to true, hit tests are performed based on the position of the
/// child as it is painted. When set to `false`, hit tests are performed /// child as it is painted. When set to false, hit tests are performed
/// ignoring the transformation. /// ignoring the transformation.
/// ///
/// applyPaintTransform(), and therefore localToGlobal() and globalToLocal(), /// applyPaintTransform(), and therefore localToGlobal() and globalToLocal(),
...@@ -1643,8 +1643,8 @@ class RenderFractionalTranslation extends RenderProxyBox { ...@@ -1643,8 +1643,8 @@ class RenderFractionalTranslation extends RenderProxyBox {
markNeedsPaint(); markNeedsPaint();
} }
/// When set to `true`, hit tests are performed based on the position of the /// When set to true, hit tests are performed based on the position of the
/// child as it is painted. When set to `false`, hit tests are performed /// child as it is painted. When set to false, hit tests are performed
/// ignoring the transformation. /// ignoring the transformation.
/// ///
/// applyPaintTransform(), and therefore localToGlobal() and globalToLocal(), /// applyPaintTransform(), and therefore localToGlobal() and globalToLocal(),
...@@ -1745,14 +1745,14 @@ abstract class CustomPainter { ...@@ -1745,14 +1745,14 @@ abstract class CustomPainter {
/// implemented in terms of the former). /// implemented in terms of the former).
/// ///
/// If the new instance represents different information than the old /// If the new instance represents different information than the old
/// instance, then the method should return `true`, otherwise it should return /// instance, then the method should return true, otherwise it should return
/// `false`. /// false.
/// ///
/// If the method returns `false`, then the [paint] call might be optimized /// If the method returns false, then the [paint] call might be optimized
/// away. /// away.
/// ///
/// It's possible that the [paint] method will get called even if /// It's possible that the [paint] method will get called even if
/// [shouldRepaint] returns `false` (e.g. if an ancestor or descendant needed to /// [shouldRepaint] returns false (e.g. if an ancestor or descendant needed to
/// be repainted). It's also possible that the [paint] method will get called /// be repainted). It's also possible that the [paint] method will get called
/// without [shouldRepaint] being called at all (e.g. if the box changes /// without [shouldRepaint] being called at all (e.g. if the box changes
/// size). /// size).
...@@ -1760,7 +1760,7 @@ abstract class CustomPainter { ...@@ -1760,7 +1760,7 @@ abstract class CustomPainter {
/// If a custom delegate has a particularly expensive paint function such that /// If a custom delegate has a particularly expensive paint function such that
/// repaints should be avoided as much as possible, a [RepaintBoundary] or /// repaints should be avoided as much as possible, a [RepaintBoundary] or
/// [RenderRepaintBoundary] (or other render object with [isRepaintBoundary] /// [RenderRepaintBoundary] (or other render object with [isRepaintBoundary]
/// set to `true`) might be helpful. /// set to true) might be helpful.
bool shouldRepaint(@checked CustomPainter oldDelegate); bool shouldRepaint(@checked CustomPainter oldDelegate);
/// Called whenever a hit test is being performed on an object that is using /// Called whenever a hit test is being performed on an object that is using
...@@ -1772,8 +1772,8 @@ abstract class CustomPainter { ...@@ -1772,8 +1772,8 @@ abstract class CustomPainter {
/// The default behavior is to consider all points to be hits for /// The default behavior is to consider all points to be hits for
/// background painters, and no points to be hits for foreground painters. /// background painters, and no points to be hits for foreground painters.
/// ///
/// Return `true` if the given position corresponds to a point on the drawn /// Return true if the given position corresponds to a point on the drawn
/// image that should be considered a "hit", `false` if it corresponds to a /// image that should be considered a "hit", false if it corresponds to a
/// point that should be considered outside the painted image, and null to use /// point that should be considered outside the painted image, and null to use
/// the default behavior. /// the default behavior.
bool hitTest(Point position) => null; bool hitTest(Point position) => null;
...@@ -1829,7 +1829,7 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -1829,7 +1829,7 @@ class RenderCustomPaint extends RenderProxyBox {
/// ///
/// If the new delegate is the same class as the previous one, then the new /// If the new delegate is the same class as the previous one, then the new
/// delegate has its [CustomPainter.shouldRepaint] called; if the result is /// delegate has its [CustomPainter.shouldRepaint] called; if the result is
/// `true`, then the delegate will be called. /// true, then the delegate will be called.
/// ///
/// If the new delegate is a different class than the previous one, then the /// If the new delegate is a different class than the previous one, then the
/// delegate will be called. /// delegate will be called.
...@@ -1854,7 +1854,7 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -1854,7 +1854,7 @@ class RenderCustomPaint extends RenderProxyBox {
/// ///
/// If the new delegate is the same class as the previous one, then the new /// If the new delegate is the same class as the previous one, then the new
/// delegate has its [CustomPainter.shouldRepaint] called; if the result is /// delegate has its [CustomPainter.shouldRepaint] called; if the result is
/// `true`, then the delegate will be called. /// true, then the delegate will be called.
/// ///
/// If the new delegate is a different class than the previous one, then the /// If the new delegate is a different class than the previous one, then the
/// delegate will be called. /// delegate will be called.
...@@ -2192,12 +2192,12 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -2192,12 +2192,12 @@ class RenderRepaintBoundary extends RenderProxyBox {
/// A render object that is invisible during hit testing. /// A render object that is invisible during hit testing.
/// ///
/// When [ignoring] is `true`, this render object (and its subtree) is invisible /// When [ignoring] is true, this render object (and its subtree) is invisible
/// to hit testing. It still consumes space during layout and paints its child /// to hit testing. It still consumes space during layout and paints its child
/// as usual. It just cannot be the target of located events, because its render /// as usual. It just cannot be the target of located events, because its render
/// object returns `false` from [hitTest]. /// object returns false from [hitTest].
/// ///
/// When [ignoringSemantics] is `true`, the subtree will be invisible to /// When [ignoringSemantics] is true, the subtree will be invisible to
/// the semantics layer (and thus e.g. accessibility tools). If /// the semantics layer (and thus e.g. accessibility tools). If
/// [ignoringSemantics] is null, it uses the value of [ignoring]. /// [ignoringSemantics] is null, it uses the value of [ignoring].
class RenderIgnorePointer extends RenderProxyBox { class RenderIgnorePointer extends RenderProxyBox {
...@@ -2378,11 +2378,11 @@ class RenderOffstage extends RenderProxyBox { ...@@ -2378,11 +2378,11 @@ class RenderOffstage extends RenderProxyBox {
/// A render object that absorbs pointers during hit testing. /// A render object that absorbs pointers during hit testing.
/// ///
/// When [absorbing] is `true`, this render object prevents its subtree from /// When [absorbing] is true, this render object prevents its subtree from
/// receiving pointer events by terminating hit testing at itself. It still /// receiving pointer events by terminating hit testing at itself. It still
/// consumes space during layout and paints its child as usual. It just prevents /// consumes space during layout and paints its child as usual. It just prevents
/// its children from being the target of located events, because its render /// its children from being the target of located events, because its render
/// object returns `true` from [hitTest]. /// object returns true from [hitTest].
class RenderAbsorbPointer extends RenderProxyBox { class RenderAbsorbPointer extends RenderProxyBox {
/// Creates a render object that absorbs pointers during hit testing. /// Creates a render object that absorbs pointers during hit testing.
/// ///
...@@ -2611,11 +2611,11 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -2611,11 +2611,11 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
assert(container != null); assert(container != null);
} }
/// If 'container' is `true`, this RenderObject will introduce a new /// If 'container' is true, this RenderObject will introduce a new
/// node in the semantics tree. Otherwise, the semantics will be /// node in the semantics tree. Otherwise, the semantics will be
/// merged with the semantics of any ancestors. /// merged with the semantics of any ancestors.
/// ///
/// The 'container' flag is implicitly set to `true` on the immediate /// The 'container' flag is implicitly set to true on the immediate
/// semantics-providing descendants of a node where multiple /// semantics-providing descendants of a node where multiple
/// children have semantics or have descendants providing semantics. /// children have semantics or have descendants providing semantics.
/// In other words, the semantics of siblings are not merged. To /// In other words, the semantics of siblings are not merged. To
...@@ -2631,7 +2631,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -2631,7 +2631,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} }
/// If non-null, sets the "hasCheckedState" semantic to `true` and the /// If non-null, sets the "hasCheckedState" semantic to true and the
/// "isChecked" semantic to the given value. /// "isChecked" semantic to the given value.
bool get checked => _checked; bool get checked => _checked;
bool _checked; bool _checked;
......
...@@ -289,7 +289,8 @@ class SemanticsNode extends AbstractNode { ...@@ -289,7 +289,8 @@ class SemanticsNode extends AbstractNode {
bool get hasCheckedState => (_flags & SemanticsFlags.hasCheckedState.index) != 0; bool get hasCheckedState => (_flags & SemanticsFlags.hasCheckedState.index) != 0;
set hasCheckedState(bool value) => _setFlag(SemanticsFlags.hasCheckedState, value); set hasCheckedState(bool value) => _setFlag(SemanticsFlags.hasCheckedState, value);
/// If this node has Boolean state that can be controlled by the user, whether that state is on or off, corresponding to `true` and `false`, respectively. /// If this node has Boolean state that can be controlled by the user, whether
/// that state is on or off, corresponding to true and false, respectively.
bool get isChecked => (_flags & SemanticsFlags.isChecked.index) != 0; bool get isChecked => (_flags & SemanticsFlags.isChecked.index) != 0;
set isChecked(bool value) => _setFlag(SemanticsFlags.isChecked, value); set isChecked(bool value) => _setFlag(SemanticsFlags.isChecked, value);
......
...@@ -736,15 +736,15 @@ abstract class SingleChildLayoutDelegate { ...@@ -736,15 +736,15 @@ abstract class SingleChildLayoutDelegate {
/// because the latter is implemented in terms of the former). /// because the latter is implemented in terms of the former).
/// ///
/// If the new instance represents different information than the old /// If the new instance represents different information than the old
/// instance, then the method should return `true`, otherwise it should return /// instance, then the method should return true, otherwise it should return
/// `false`. /// false.
/// ///
/// If the method returns `false`, then the [getSize], /// If the method returns false, then the [getSize],
/// [getConstraintsForChild], and [getPositionForChild] calls might be /// [getConstraintsForChild], and [getPositionForChild] calls might be
/// optimized away. /// optimized away.
/// ///
/// It's possible that the layout methods will get called even if /// It's possible that the layout methods will get called even if
/// [shouldRelayout] returns `false` (e.g. if an ancestor changed its layout). /// [shouldRelayout] returns false (e.g. if an ancestor changed its layout).
/// It's also possible that the layout method will get called /// It's also possible that the layout method will get called
/// without [shouldRelayout] being called at all (e.g. if the parent changes /// without [shouldRelayout] being called at all (e.g. if the parent changes
/// size). /// size).
......
...@@ -54,10 +54,10 @@ abstract class AssetBundle { ...@@ -54,10 +54,10 @@ abstract class AssetBundle {
/// Retrieve a string from the asset bundle. /// Retrieve a string from the asset bundle.
/// ///
/// If the `cache` argument is set to `false`, then the data will not be /// If the `cache` argument is set to false, then the data will not be
/// cached, and reading the data may bypass the cache. This is useful if the /// cached, and reading the data may bypass the cache. This is useful if the
/// caller is going to be doing its own caching. (It might not be cached if /// caller is going to be doing its own caching. (It might not be cached if
/// it's set to `true` either, that depends on the asset bundle /// it's set to true either, that depends on the asset bundle
/// implementation.) /// implementation.)
Future<String> loadString(String key, { bool cache: true }); Future<String> loadString(String key, { bool cache: true });
......
...@@ -2872,12 +2872,12 @@ class RepaintBoundary extends SingleChildRenderObjectWidget { ...@@ -2872,12 +2872,12 @@ class RepaintBoundary extends SingleChildRenderObjectWidget {
/// A widget that is invisible during hit testing. /// A widget that is invisible during hit testing.
/// ///
/// When [ignoring] is `true`, this widget (and its subtree) is invisible /// When [ignoring] is true, this widget (and its subtree) is invisible
/// to hit testing. It still consumes space during layout and paints its child /// to hit testing. It still consumes space during layout and paints its child
/// as usual. It just cannot be the target of located events, because it returns /// as usual. It just cannot be the target of located events, because it returns
/// `false` from [hitTest]. /// false from [hitTest].
/// ///
/// When [ignoringSemantics] is `true`, the subtree will be invisible to /// When [ignoringSemantics] is true, the subtree will be invisible to
/// the semantics layer (and thus e.g. accessibility tools). If /// the semantics layer (and thus e.g. accessibility tools). If
/// [ignoringSemantics] is null, it uses the value of [ignoring]. /// [ignoringSemantics] is null, it uses the value of [ignoring].
/// ///
...@@ -2936,10 +2936,10 @@ class IgnorePointer extends SingleChildRenderObjectWidget { ...@@ -2936,10 +2936,10 @@ class IgnorePointer extends SingleChildRenderObjectWidget {
/// A widget that absorbs pointers during hit testing. /// A widget that absorbs pointers during hit testing.
/// ///
/// When [absorbing] is `true`, this widget prevents its subtree from receiving /// When [absorbing] is true, this widget prevents its subtree from receiving
/// pointer events by terminating hit testing at itself. It still consumes space /// pointer events by terminating hit testing at itself. It still consumes space
/// during layout and paints its child as usual. It just prevents its children /// during layout and paints its child as usual. It just prevents its children
/// from being the target of located events, because it returns `true` from /// from being the target of located events, because it returns true from
/// [hitTest]. /// [hitTest].
/// ///
/// See also: /// See also:
......
...@@ -347,7 +347,7 @@ class TypeMatcher<T> { ...@@ -347,7 +347,7 @@ class TypeMatcher<T> {
/// Creates a type matcher for the given type parameter. /// Creates a type matcher for the given type parameter.
const TypeMatcher(); const TypeMatcher();
/// Returns `true` if the given object is of type `T`. /// Returns true if the given object is of type `T`.
bool check(dynamic object) => object is T; bool check(dynamic object) => object is T;
} }
...@@ -397,6 +397,13 @@ abstract class Widget { ...@@ -397,6 +397,13 @@ abstract class Widget {
/// new widget). Otherwise, the old element is removed from the tree, the new /// 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 /// widget is inflated into an element, and the new element is inserted into the
/// tree. /// tree.
///
/// 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.
final Key key; final Key key;
/// Inflates this configuration to a concrete instance. /// Inflates this configuration to a concrete instance.
...@@ -443,6 +450,10 @@ abstract class Widget { ...@@ -443,6 +450,10 @@ abstract class Widget {
/// An element that uses a given widget as its configuration can be updated to /// 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 /// use another widget as its configuration if, and only if, the two widgets
/// have [runtimeType] and [key] properties that are [operator==]. /// have [runtimeType] and [key] properties that are [operator==].
///
/// 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.
static bool canUpdate(Widget oldWidget, Widget newWidget) { static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key; && oldWidget.key == newWidget.key;
......
...@@ -981,7 +981,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin { ...@@ -981,7 +981,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
/// ///
/// The given `route` must have already received a call to [Route.didPop]. /// The given `route` must have already received a call to [Route.didPop].
/// This function may be called directly from [Route.didPop] if [Route.didPop] /// This function may be called directly from [Route.didPop] if [Route.didPop]
/// will return `true`. /// will return true.
void finalizeRoute(Route<dynamic> route) { void finalizeRoute(Route<dynamic> route) {
_poppedRoutes.remove(route); _poppedRoutes.remove(route);
route.dispose(); route.dispose();
......
...@@ -19,7 +19,7 @@ import 'framework.dart'; ...@@ -19,7 +19,7 @@ import 'framework.dart';
/// ///
/// The simplest way to show the performance overlay is to set /// The simplest way to show the performance overlay is to set
/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]
/// to `true`. /// to true.
class PerformanceOverlay extends LeafRenderObjectWidget { class PerformanceOverlay extends LeafRenderObjectWidget {
// TODO(abarth): We should have a page on the web site with a screenshot and // TODO(abarth): We should have a page on the web site with a screenshot and
// an explanation of all the various readouts. // an explanation of all the various readouts.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment