Commit 63962d2c authored by Ian Hickson's avatar Ian Hickson

Merge pull request #1299 from Hixie/inherited-perf

Reimplement Inherited.notifyDescendants to use a registration list
parents 0911e5d3 0903cb5f
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
library stocks; library stocks;
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' as ui; import 'dart:ui' as ui;
......
...@@ -203,7 +203,7 @@ class StockHomeState extends State<StockHome> { ...@@ -203,7 +203,7 @@ class StockHomeState extends State<StockHome> {
stocks: stocks.toList(), stocks: stocks.toList(),
onAction: _buyStock, onAction: _buyStock,
onOpen: (Stock stock, Key arrowKey) { onOpen: (Stock stock, Key arrowKey) {
Set<Key> mostValuableKeys = new Set<Key>(); Set<Key> mostValuableKeys = new HashSet<Key>();
mostValuableKeys.add(arrowKey); mostValuableKeys.add(arrowKey);
Navigator.pushNamed(context, '/stock/${stock.symbol}', mostValuableKeys: mostValuableKeys); Navigator.pushNamed(context, '/stock/${stock.symbol}', mostValuableKeys: mostValuableKeys);
}, },
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
/// An implementation of the Cassowary constraint solving algorithm in Dart. /// An implementation of the Cassowary constraint solving algorithm in Dart.
library cassowary; library cassowary;
import 'dart:collection';
import 'dart:math'; import 'dart:math';
part 'constraint.dart'; part 'constraint.dart';
......
...@@ -146,13 +146,11 @@ class Solver { ...@@ -146,13 +146,11 @@ class Solver {
Result removeEditVariable(Variable variable) { Result removeEditVariable(Variable variable) {
_EditInfo info = _edits[variable]; _EditInfo info = _edits[variable];
if (info == null) { if (info == null)
return Result.unknownEditVariable; return Result.unknownEditVariable;
}
if (removeConstraint(info.constraint) != Result.success) { if (removeConstraint(info.constraint) != Result.success)
return Result.internalSolverError; return Result.internalSolverError;
}
_edits.remove(variable); _edits.remove(variable);
return Result.success; return Result.success;
...@@ -173,7 +171,7 @@ class Solver { ...@@ -173,7 +171,7 @@ class Solver {
} }
Set flushUpdates() { Set flushUpdates() {
Set updates = new Set(); Set updates = new HashSet<dynamic>();
for (Variable variable in _vars.keys) { for (Variable variable in _vars.keys) {
_Symbol symbol = _vars[variable]; _Symbol symbol = _vars[variable];
...@@ -183,12 +181,10 @@ class Solver { ...@@ -183,12 +181,10 @@ class Solver {
if (variable._applyUpdate(updatedValue) && variable._owner != null) { if (variable._applyUpdate(updatedValue) && variable._owner != null) {
dynamic context = variable._owner.context; dynamic context = variable._owner.context;
if (context != null)
if (context != null) {
updates.add(context); updates.add(context);
} }
} }
}
return updates; return updates;
} }
...@@ -212,10 +208,9 @@ class Solver { ...@@ -212,10 +208,9 @@ class Solver {
} }
if (needsCleanup) { if (needsCleanup) {
for (dynamic item in applied.reversed) { for (dynamic item in applied.reversed)
undoer(item); undoer(item);
} }
}
return result; return result;
} }
...@@ -223,9 +218,8 @@ class Solver { ...@@ -223,9 +218,8 @@ class Solver {
_Symbol _symbolForVariable(Variable variable) { _Symbol _symbolForVariable(Variable variable) {
_Symbol symbol = _vars[variable]; _Symbol symbol = _vars[variable];
if (symbol != null) { if (symbol != null)
return symbol; return symbol;
}
symbol = new _Symbol(_SymbolType.external, tick++); symbol = new _Symbol(_SymbolType.external, tick++);
_vars[variable] = symbol; _vars[variable] = symbol;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:ui' show Point, Offset; import 'dart:ui' show Point, Offset;
import 'arena.dart'; import 'arena.dart';
...@@ -43,7 +44,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -43,7 +44,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
GestureArena _gestureArena; GestureArena _gestureArena;
final List<GestureArenaEntry> _entries = <GestureArenaEntry>[]; final List<GestureArenaEntry> _entries = <GestureArenaEntry>[];
final Set<int> _trackedPointers = new Set<int>(); final Set<int> _trackedPointers = new HashSet<int>();
void handleEvent(PointerEvent event); void handleEvent(PointerEvent event);
void acceptGesture(int pointer) { } void acceptGesture(int pointer) { }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -85,7 +87,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> { ...@@ -85,7 +87,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> {
} // else we're probably in deactivate() } // else we're probably in deactivate()
} }
); );
_splashes ??= new Set<InkSplash>(); _splashes ??= new HashSet<InkSplash>();
_splashes.add(splash); _splashes.add(splash);
_currentSplash = splash; _currentSplash = splash;
updateHighlight(true); updateHighlight(true);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:developer'; import 'dart:developer';
import 'dart:ui' as ui; import 'dart:ui' as ui;
...@@ -142,7 +143,7 @@ abstract class Scheduler extends BindingBase { ...@@ -142,7 +143,7 @@ abstract class Scheduler extends BindingBase {
int _nextFrameCallbackId = 0; // positive int _nextFrameCallbackId = 0; // positive
Map<int, FrameCallback> _transientCallbacks = <int, FrameCallback>{}; Map<int, FrameCallback> _transientCallbacks = <int, FrameCallback>{};
final Set<int> _removedIds = new Set<int>(); final Set<int> _removedIds = new HashSet<int>();
int get transientCallbackCount => _transientCallbacks.length; int get transientCallbackCount => _transientCallbacks.length;
......
...@@ -105,6 +105,18 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Rendere ...@@ -105,6 +105,18 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Rendere
_dirtyElements.add(element); _dirtyElements.add(element);
} }
static int _elementSort(BuildableElement a, BuildableElement b) {
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;
}
/// Builds all the elements that were marked as dirty using schedule(), in depth order. /// Builds all the elements that were marked as dirty using schedule(), in depth order.
/// If elements are marked as dirty while this runs, they must be deeper than the algorithm /// If elements are marked as dirty while this runs, they must be deeper than the algorithm
/// has yet reached. /// has yet reached.
...@@ -114,14 +126,14 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Rendere ...@@ -114,14 +126,14 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Rendere
return; return;
Timeline.startSync('Build'); Timeline.startSync('Build');
BuildableElement.lockState(() { BuildableElement.lockState(() {
_dirtyElements.sort((BuildableElement a, BuildableElement b) => a.depth - b.depth); _dirtyElements.sort(_elementSort);
int dirtyCount = _dirtyElements.length; int dirtyCount = _dirtyElements.length;
int index = 0; int index = 0;
while (index < dirtyCount) { while (index < dirtyCount) {
_dirtyElements[index].rebuild(); _dirtyElements[index].rebuild();
index += 1; index += 1;
if (dirtyCount < _dirtyElements.length) { if (dirtyCount < _dirtyElements.length) {
_dirtyElements.sort((BuildableElement a, BuildableElement b) => a.depth - b.depth); _dirtyElements.sort(_elementSort);
dirtyCount = _dirtyElements.length; dirtyCount = _dirtyElements.length;
} }
} }
......
...@@ -81,7 +81,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key { ...@@ -81,7 +81,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key {
static final Map<GlobalKey, Element> _registry = new Map<GlobalKey, Element>(); static final Map<GlobalKey, Element> _registry = new Map<GlobalKey, Element>();
static final Map<GlobalKey, int> _debugDuplicates = new Map<GlobalKey, int>(); static final Map<GlobalKey, int> _debugDuplicates = new Map<GlobalKey, int>();
static final Map<GlobalKey, Set<GlobalKeyRemoveListener>> _removeListeners = new Map<GlobalKey, Set<GlobalKeyRemoveListener>>(); static final Map<GlobalKey, Set<GlobalKeyRemoveListener>> _removeListeners = new Map<GlobalKey, Set<GlobalKeyRemoveListener>>();
static final Set<GlobalKey> _removedKeys = new Set<GlobalKey>(); static final Set<GlobalKey> _removedKeys = new HashSet<GlobalKey>();
void _register(Element element) { void _register(Element element) {
assert(() { assert(() {
...@@ -129,7 +129,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key { ...@@ -129,7 +129,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key {
static void registerRemoveListener(GlobalKey key, GlobalKeyRemoveListener listener) { static void registerRemoveListener(GlobalKey key, GlobalKeyRemoveListener listener) {
assert(key != null); assert(key != null);
Set<GlobalKeyRemoveListener> listeners = Set<GlobalKeyRemoveListener> listeners =
_removeListeners.putIfAbsent(key, () => new Set<GlobalKeyRemoveListener>()); _removeListeners.putIfAbsent(key, () => new HashSet<GlobalKeyRemoveListener>());
bool added = listeners.add(listener); bool added = listeners.add(listener);
assert(added); assert(added);
} }
...@@ -160,7 +160,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key { ...@@ -160,7 +160,7 @@ abstract class GlobalKey<T extends State<StatefulComponent>> extends Key {
try { try {
for (GlobalKey key in _removedKeys) { for (GlobalKey key in _removedKeys) {
if (!_registry.containsKey(key) && _removeListeners.containsKey(key)) { if (!_registry.containsKey(key) && _removeListeners.containsKey(key)) {
Set<GlobalKeyRemoveListener> localListeners = new Set<GlobalKeyRemoveListener>.from(_removeListeners[key]); Set<GlobalKeyRemoveListener> localListeners = new HashSet<GlobalKeyRemoveListener>.from(_removeListeners[key]);
for (GlobalKeyRemoveListener listener in localListeners) for (GlobalKeyRemoveListener listener in localListeners)
listener(key); listener(key);
} }
...@@ -524,7 +524,7 @@ enum _ElementLifecycle { ...@@ -524,7 +524,7 @@ enum _ElementLifecycle {
class _InactiveElements { class _InactiveElements {
bool _locked = false; bool _locked = false;
final Set<Element> _elements = new Set<Element>(); final Set<Element> _elements = new HashSet<Element>();
void _unmount(Element element) { void _unmount(Element element) {
assert(element._debugLifecycleState == _ElementLifecycle.inactive); assert(element._debugLifecycleState == _ElementLifecycle.inactive);
...@@ -554,6 +554,7 @@ class _InactiveElements { ...@@ -554,6 +554,7 @@ class _InactiveElements {
element.deactivate(); element.deactivate();
assert(element._debugLifecycleState == _ElementLifecycle.inactive); assert(element._debugLifecycleState == _ElementLifecycle.inactive);
element.visitChildren(_deactivate); element.visitChildren(_deactivate);
assert(() { element.debugDeactivated(); return true; });
} }
void add(Element element) { void add(Element element) {
...@@ -565,20 +566,12 @@ class _InactiveElements { ...@@ -565,20 +566,12 @@ class _InactiveElements {
_elements.add(element); _elements.add(element);
} }
void _reactivate(Element element) {
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
element.reactivate();
assert(element._debugLifecycleState == _ElementLifecycle.active);
element.visitChildren(_reactivate);
}
void remove(Element element) { void remove(Element element) {
assert(!_locked); assert(!_locked);
assert(_elements.contains(element)); assert(_elements.contains(element));
assert(element._parent == null); assert(element._parent == null);
_elements.remove(element); _elements.remove(element);
assert(!element._active); assert(!element._active);
_reactivate(element);
} }
} }
...@@ -728,6 +721,7 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -728,6 +721,7 @@ abstract class Element<T extends Widget> implements BuildContext {
final GlobalKey key = widget.key; final GlobalKey key = widget.key;
key._register(this); key._register(this);
} }
_updateInheritance();
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; }); assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
} }
...@@ -792,7 +786,7 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -792,7 +786,7 @@ abstract class Element<T extends Widget> implements BuildContext {
_slot = newSlot; _slot = newSlot;
} }
Element _findAndActivateElement(GlobalKey key, Widget newWidget) { Element _retakeInactiveElement(GlobalKey key, Widget newWidget) {
Element element = key._currentElement; Element element = key._currentElement;
if (element == null) if (element == null)
return null; return null;
...@@ -808,13 +802,11 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -808,13 +802,11 @@ abstract class Element<T extends Widget> implements BuildContext {
Element _inflateWidget(Widget newWidget, dynamic newSlot) { Element _inflateWidget(Widget newWidget, dynamic newSlot) {
Key key = newWidget.key; Key key = newWidget.key;
if (key is GlobalKey) { if (key is GlobalKey) {
Element newChild = _findAndActivateElement(key, newWidget); Element newChild = _retakeInactiveElement(key, newWidget);
if (newChild != null) { if (newChild != null) {
assert(newChild._parent == null); assert(newChild._parent == null);
assert(() { _debugCheckForCycles(newChild); return true; }); assert(() { _debugCheckForCycles(newChild); return true; });
newChild._parent = this; newChild.activate(this, newSlot);
newChild._updateDepth();
newChild.attachRenderObject(newSlot);
Element updatedChild = updateChild(newChild, newWidget, newSlot); Element updatedChild = updateChild(newChild, newWidget, newSlot);
assert(newChild == updatedChild); assert(newChild == updatedChild);
return updatedChild; return updatedChild;
...@@ -846,22 +838,43 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -846,22 +838,43 @@ abstract class Element<T extends Widget> implements BuildContext {
_inactiveElements.add(child); // this eventually calls child.deactivate() _inactiveElements.add(child); // this eventually calls child.deactivate()
} }
void activate(Element parent, dynamic newSlot) {
assert(_debugLifecycleState == _ElementLifecycle.inactive);
_reactivate();
_parent = parent;
_updateDepth();
_updateInheritance();
attachRenderObject(newSlot);
assert(_debugLifecycleState == _ElementLifecycle.active);
}
void _reactivate() {
assert(_debugLifecycleState == _ElementLifecycle.inactive);
assert(widget != null);
assert(depth != null);
assert(!_active);
_active = true;
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
visitChildren((Element child) => child._reactivate());
}
void deactivate() { void deactivate() {
assert(_debugLifecycleState == _ElementLifecycle.active); assert(_debugLifecycleState == _ElementLifecycle.active);
assert(widget != null); assert(widget != null);
assert(depth != null); assert(depth != null);
assert(_active); assert(_active);
if (_dependencies != null) {
for (InheritedElement dependency in _dependencies)
dependency._dependants.remove(this);
_dependencies.clear();
}
_active = false; _active = false;
assert(() { _debugLifecycleState = _ElementLifecycle.inactive; return true; }); assert(() { _debugLifecycleState = _ElementLifecycle.inactive; return true; });
} }
void reactivate() { /// Called after children have been deactivated.
void debugDeactivated() {
assert(_debugLifecycleState == _ElementLifecycle.inactive); assert(_debugLifecycleState == _ElementLifecycle.inactive);
assert(widget != null);
assert(depth != null);
assert(!_active);
_active = true;
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
} }
/// Called when an Element is removed from the tree permanently. /// Called when an Element is removed from the tree permanently.
...@@ -879,12 +892,22 @@ abstract class Element<T extends Widget> implements BuildContext { ...@@ -879,12 +892,22 @@ abstract class Element<T extends Widget> implements BuildContext {
RenderObject findRenderObject() => renderObject; RenderObject findRenderObject() => renderObject;
Set<Type> _dependencies; Map<Type, InheritedElement> _inheritedWidgets;
Set<InheritedElement> _dependencies;
InheritedWidget inheritFromWidgetOfExactType(Type targetType) { InheritedWidget inheritFromWidgetOfExactType(Type targetType) {
if (_dependencies == null) InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
_dependencies = new Set<Type>(); if (ancestor != null) {
_dependencies.add(targetType); assert(ancestor is InheritedElement);
return ancestorWidgetOfExactType(targetType); _dependencies ??= new HashSet<InheritedElement>();
_dependencies.add(ancestor);
ancestor._dependants.add(this);
return ancestor.widget;
}
return null;
}
void _updateInheritance() {
_inheritedWidgets = _parent?._inheritedWidgets;
} }
Widget ancestorWidgetOfExactType(Type targetType) { Widget ancestorWidgetOfExactType(Type targetType) {
...@@ -1359,19 +1382,39 @@ class ParentDataElement extends _ProxyElement<ParentDataWidget> { ...@@ -1359,19 +1382,39 @@ class ParentDataElement extends _ProxyElement<ParentDataWidget> {
class InheritedElement extends _ProxyElement<InheritedWidget> { class InheritedElement extends _ProxyElement<InheritedWidget> {
InheritedElement(InheritedWidget widget) : super(widget); InheritedElement(InheritedWidget widget) : super(widget);
final Set<Element> _dependants = new HashSet<Element>();
void _updateInheritance() {
final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
if (incomingWidgets != null)
_inheritedWidgets = new Map<Type, InheritedElement>.from(incomingWidgets);
else
_inheritedWidgets = new Map<Type, InheritedElement>();
_inheritedWidgets[widget.runtimeType] = this;
}
void debugDeactivated() {
assert(() {
assert(_dependants.isEmpty);
return true;
});
super.debugDeactivated();
}
void notifyDescendants(InheritedWidget oldWidget) { void notifyDescendants(InheritedWidget oldWidget) {
if (!widget.updateShouldNotify(oldWidget)) if (!widget.updateShouldNotify(oldWidget))
return; return;
final Type ourRuntimeType = widget.runtimeType; final Type ourRuntimeType = widget.runtimeType;
void notifyChildren(Element child) { for (Element dependant in _dependants) {
if (child._dependencies != null && dependant.dependenciesChanged(ourRuntimeType);
child._dependencies.contains(ourRuntimeType)) { assert(() {
child.dependenciesChanged(ourRuntimeType); // check that it really is our descendant
} Element ancestor = dependant._parent;
if (child.runtimeType != ourRuntimeType) while (ancestor != this && ancestor != null)
child.visitChildren(notifyChildren); ancestor = ancestor._parent;
return ancestor == this;
});
} }
visitChildren(notifyChildren);
} }
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
...@@ -98,7 +100,7 @@ class Hero extends StatefulComponent { ...@@ -98,7 +100,7 @@ class Hero extends StatefulComponent {
final bool alwaysAnimate; final bool alwaysAnimate;
static Map<Object, HeroHandle> of(BuildContext context, Set<Key> mostValuableKeys) { static Map<Object, HeroHandle> of(BuildContext context, Set<Key> mostValuableKeys) {
mostValuableKeys ??= new Set<Key>(); mostValuableKeys ??= new HashSet<Key>();
assert(!mostValuableKeys.contains(null)); assert(!mostValuableKeys.contains(null));
// first we collect ALL the heroes, sorted by their tags // first we collect ALL the heroes, sorted by their tags
Map<Object, Map<Key, HeroState>> heroes = <Object, Map<Key, HeroState>>{}; Map<Object, Map<Key, HeroState>> heroes = <Object, Map<Key, HeroState>>{};
...@@ -177,7 +179,7 @@ class HeroState extends State<Hero> implements HeroHandle { ...@@ -177,7 +179,7 @@ class HeroState extends State<Hero> implements HeroHandle {
_HeroManifest result = new _HeroManifest( _HeroManifest result = new _HeroManifest(
key: _key, key: _key,
config: config, config: config,
sourceStates: new Set<HeroState>.from(<HeroState>[this]), sourceStates: new HashSet<HeroState>.from(<HeroState>[this]),
currentRect: startRect, currentRect: startRect,
currentTurns: config.turns.toDouble() currentTurns: config.turns.toDouble()
); );
...@@ -268,7 +270,7 @@ class _HeroQuestState implements HeroHandle { ...@@ -268,7 +270,7 @@ class _HeroQuestState implements HeroHandle {
_taken = true; _taken = true;
Set<HeroState> states = sourceStates; Set<HeroState> states = sourceStates;
if (targetState != null) if (targetState != null)
states = states.union(new Set<HeroState>.from(<HeroState>[targetState])); states = states.union(new HashSet<HeroState>.from(<HeroState>[targetState]));
return new _HeroManifest( return new _HeroManifest(
key: key, key: key,
config: child, config: child,
...@@ -351,7 +353,7 @@ class HeroParty { ...@@ -351,7 +353,7 @@ class HeroParty {
assert(to == null || to.sourceStates.length == 1); assert(to == null || to.sourceStates.length == 1);
assert(to == null || to.currentTurns.floor() == to.currentTurns); assert(to == null || to.currentTurns.floor() == to.currentTurns);
HeroState targetState = to != null ? to.sourceStates.elementAt(0) : null; HeroState targetState = to != null ? to.sourceStates.elementAt(0) : null;
Set<HeroState> sourceStates = from != null ? from.sourceStates : new Set<HeroState>(); Set<HeroState> sourceStates = from != null ? from.sourceStates : new HashSet<HeroState>();
sourceStates.remove(targetState); sourceStates.remove(targetState);
RelativeRect sourceRect = from != null ? from.currentRect : RelativeRect sourceRect = from != null ? from.currentRect :
new RelativeRect.fromRect(to.currentRect.toRect(animationArea).center & Size.zero, animationArea); new RelativeRect.fromRect(to.currentRect.toRect(animationArea).center & Size.zero, animationArea);
...@@ -489,7 +491,7 @@ class HeroController extends NavigatorObserver { ...@@ -489,7 +491,7 @@ class HeroController extends NavigatorObserver {
Set<Key> _getMostValuableKeys() { Set<Key> _getMostValuableKeys() {
assert(_from != null); assert(_from != null);
assert(_to != null); assert(_to != null);
Set<Key> result = new Set<Key>(); Set<Key> result = new HashSet<Key>();
if (_from.settings.mostValuableKeys != null) if (_from.settings.mostValuableKeys != null)
result.addAll(_from.settings.mostValuableKeys); result.addAll(_from.settings.mostValuableKeys);
if (_to.settings.mostValuableKeys != null) if (_to.settings.mostValuableKeys != null)
......
...@@ -21,7 +21,7 @@ class LocaleQuery<T extends LocaleQueryData> extends InheritedWidget { ...@@ -21,7 +21,7 @@ class LocaleQuery<T extends LocaleQueryData> extends InheritedWidget {
/// The data from the closest instance of this class that encloses the given context. /// The data from the closest instance of this class that encloses the given context.
static LocaleQueryData of(BuildContext context) { static LocaleQueryData of(BuildContext context) {
LocaleQuery query = context.inheritFromWidgetOfExactType(LocaleQuery); LocaleQuery query = context.inheritFromWidgetOfExactType(LocaleQuery);
return query == null ? null : query.data; return query?.data;
} }
bool updateShouldNotify(LocaleQuery old) => data != old.data; bool updateShouldNotify(LocaleQuery old) => data != old.data;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -97,7 +99,7 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> { ...@@ -97,7 +99,7 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> {
Map<_ChildKey, Element> _childrenByKey = new Map<_ChildKey, Element>(); Map<_ChildKey, Element> _childrenByKey = new Map<_ChildKey, Element>();
/// The child offsets that we've been told are invalid. /// The child offsets that we've been told are invalid.
final Set<int> _invalidIndices = new Set<int>(); final Set<int> _invalidIndices = new HashSet<int>();
/// Returns false if any of the previously-cached offsets have been marked as /// Returns false if any of the previously-cached offsets have been marked as
/// invalid and need to be updated. /// invalid and need to be updated.
......
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:collection';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
final List<String> results = <String>[]; final List<String> results = <String>[];
Set<TestRoute> routes = new Set<TestRoute>(); Set<TestRoute> routes = new HashSet<TestRoute>();
class TestRoute extends Route<String> { class TestRoute extends Route<String> {
TestRoute(this.name); TestRoute(this.name);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
...@@ -31,7 +32,7 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -31,7 +32,7 @@ class AnalyzeCommand extends FlutterCommand {
@override @override
Future<int> runInProject() async { Future<int> runInProject() async {
Stopwatch stopwatch = new Stopwatch()..start(); Stopwatch stopwatch = new Stopwatch()..start();
Set<String> pubSpecDirectories = new Set<String>(); Set<String> pubSpecDirectories = new HashSet<String>();
List<String> dartFiles = argResults.rest.toList(); List<String> dartFiles = argResults.rest.toList();
bool foundAnyInCurrentDirectory = false; bool foundAnyInCurrentDirectory = false;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
...@@ -32,7 +33,7 @@ class RemoteListener { ...@@ -32,7 +33,7 @@ class RemoteListener {
final Suite _suite; final Suite _suite;
final WebSocket _socket; final WebSocket _socket;
final Set<LiveTest> _liveTests = new Set<LiveTest>(); final Set<LiveTest> _liveTests = new HashSet<LiveTest>();
static Future start(String server, Metadata metadata, Function getMain()) async { static Future start(String server, Metadata metadata, Function getMain()) async {
WebSocket socket = await WebSocket.connect(server); WebSocket socket = await WebSocket.connect(server);
......
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