From 78d35391ce0c2abc82098a87824f29b915530393 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 3 Nov 2015 14:14:19 -0800 Subject: [PATCH] Stocks list doesn't update when stocks are loaded Previously, we passed widgets up the hierarchy to display them in the overlay, but that breaks the change propagation logic because those widgets won't get rebuilt. Now we pass WidgetBuilders instead, which can be rebuilt when the overlay rebuilds. Fixes #1913 --- .../lib/src/material/bottom_sheet.dart | 2 +- packages/flutter/lib/src/material/dialog.dart | 2 +- packages/flutter/lib/src/material/drawer.dart | 4 +++- .../flutter/lib/src/material/dropdown.dart | 8 +++---- .../flutter/lib/src/material/popup_menu.dart | 2 +- .../flutter/lib/src/widgets/drag_target.dart | 10 ++++----- .../lib/src/widgets/hero_controller.dart | 2 +- .../lib/src/widgets/modal_barrier.dart | 21 +++++++++++-------- packages/flutter/lib/src/widgets/overlay.dart | 20 +++++++----------- packages/flutter/lib/src/widgets/page.dart | 2 +- packages/flutter/lib/src/widgets/routes.dart | 7 +++---- packages/unit/test/widget/heroes_test.dart | 3 ++- 12 files changed, 41 insertions(+), 42 deletions(-) diff --git a/packages/flutter/lib/src/material/bottom_sheet.dart b/packages/flutter/lib/src/material/bottom_sheet.dart index fa5c8e5ac21..2802ffa0b9f 100644 --- a/packages/flutter/lib/src/material/bottom_sheet.dart +++ b/packages/flutter/lib/src/material/bottom_sheet.dart @@ -108,7 +108,7 @@ class _ModalBottomSheetRoute extends ModalRoute { } Color get barrierColor => Colors.black54; - Widget createModalWidget() => new _BottomSheet(route: this); + Widget buildModalWidget(BuildContext context) => new _BottomSheet(route: this); void didPop([dynamic result]) { completer.complete(result); diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 905200a134c..744533fb4ee 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -125,7 +125,7 @@ class _DialogRoute extends ModalRoute { Duration get transitionDuration => const Duration(milliseconds: 150); Color get barrierColor => Colors.black54; - Widget createModalWidget() { + Widget buildModalWidget(BuildContext context) { return new FadeTransition( performance: performance, opacity: new AnimatedValue(0.0, end: 1.0, curve: Curves.easeOut), diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index ef5827491ec..2cb4347570a 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -109,7 +109,9 @@ class _DrawerRoute extends TransitionRoute { return _performance; } - List createWidgets() => [ new _Drawer(route: this) ]; + List get builders => [ _build ]; + + Widget _build(BuildContext context) => new _Drawer(route: this); void didPop([dynamic result]) { assert(result == null); // because we don't do anything with it, so otherwise it'd be lost diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index 4905a505f60..cc975a567e9 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -138,10 +138,10 @@ class _MenuRoute extends TransitionRoute { bool get opaque => false; Duration get transitionDuration => _kMenuDuration; - List createWidgets() => [ - new ModalBarrier(), - new _DropdownMenu(route: this) - ]; + Widget _buildModalBarrier(BuildContext context) => new ModalBarrier(); + Widget _buildDropDownMenu(BuildContext context) => new _DropdownMenu(route: this); + + List get builders => [ _buildModalBarrier, _buildDropDownMenu ]; void didPop([dynamic result]) { completer.complete(result); diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index f45b1d1eee5..6c8231364f2 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -114,7 +114,7 @@ class _MenuRoute extends ModalRoute { bool get opaque => false; Duration get transitionDuration => _kMenuDuration; - Widget createModalWidget() => new _PopupMenu(route: this); + Widget buildModalWidget(BuildContext context) => new _PopupMenu(route: this); void didPop([dynamic result]) { completer.complete(result); diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 7ec634b81e3..99abd503827 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -89,13 +89,13 @@ class _DraggableState extends State { } ); _avatar.update(point); - _avatar.rebuild(context); + _avatar.markNeedsBuild(context); } void _updateDrag(PointerInputEvent event) { if (_avatar != null) { _avatar.update(new Point(event.x, event.y)); - _avatar.rebuild(context); + _avatar.markNeedsBuild(context); } } @@ -223,12 +223,12 @@ class _DragAvatar { _activeTargetWillAcceptDrop = _activeTarget != null && _activeTarget.didEnter(data); } - void rebuild(BuildContext context) { + void markNeedsBuild(BuildContext context) { if (_entry == null) { - _entry = new OverlayEntry(child: _build(context)); + _entry = new OverlayEntry(builder: _build); Navigator.of(context).overlay.insert(_entry); } else { - _entry.child = _build(context); + _entry.markNeedsBuild(); } } diff --git a/packages/flutter/lib/src/widgets/hero_controller.dart b/packages/flutter/lib/src/widgets/hero_controller.dart index cf51afabfc0..14cce393bc7 100644 --- a/packages/flutter/lib/src/widgets/hero_controller.dart +++ b/packages/flutter/lib/src/widgets/hero_controller.dart @@ -72,7 +72,7 @@ class HeroController { void _addHeroesToOverlay(Iterable heroes, OverlayState overlay) { for (Widget hero in heroes) { - OverlayEntry entry = new OverlayEntry(child: hero); + OverlayEntry entry = new OverlayEntry(builder: (_) => hero); overlay.insert(entry); _overlayEntries.add(entry); } diff --git a/packages/flutter/lib/src/widgets/modal_barrier.dart b/packages/flutter/lib/src/widgets/modal_barrier.dart index edcef27ddce..6b2cd17c139 100644 --- a/packages/flutter/lib/src/widgets/modal_barrier.dart +++ b/packages/flutter/lib/src/widgets/modal_barrier.dart @@ -111,15 +111,18 @@ class ModalPosition { abstract class ModalRoute extends TransitionRoute { ModalPosition get position => null; Color get barrierColor => _kTransparent; - Widget createModalWidget(); + Widget buildModalWidget(BuildContext context); - List createWidgets() { - return [ - new _AnimatedModalBarrier( - color: new AnimatedColorValue(_kTransparent, end: barrierColor, curve: Curves.ease), - performance: performance - ), - new _ModalScope(route: this, child: createModalWidget()), - ]; + Widget _buildModalBarrier(BuildContext context) { + return new _AnimatedModalBarrier( + color: new AnimatedColorValue(_kTransparent, end: barrierColor, curve: Curves.ease), + performance: performance + ); } + + Widget _buildModalScope(BuildContext context) { + return new _ModalScope(route: this, child: buildModalWidget(context)); + } + + List get builders => [ _buildModalBarrier, _buildModalScope ]; } diff --git a/packages/flutter/lib/src/widgets/overlay.dart b/packages/flutter/lib/src/widgets/overlay.dart index d69eb55d9ca..048a65d2c89 100644 --- a/packages/flutter/lib/src/widgets/overlay.dart +++ b/packages/flutter/lib/src/widgets/overlay.dart @@ -7,18 +7,11 @@ import 'framework.dart'; class OverlayEntry { OverlayEntry({ - Widget child, + this.builder, bool opaque: false - }) : _child = child, _opaque = opaque; + }) : _opaque = opaque; - Widget get child => _child; - Widget _child; - void set child (Widget value) { - if (_child == value) - return; - _child = value; - _rebuild(); - } + final WidgetBuilder builder; bool get opaque => _opaque; bool _opaque; @@ -26,7 +19,7 @@ class OverlayEntry { if (_opaque == value) return; _opaque = value; - _rebuild(); + markNeedsBuild(); } OverlayState _state; @@ -37,7 +30,8 @@ class OverlayEntry { _state = null; } - void _rebuild() { + void markNeedsBuild() { + // TODO(ianh): find a way to make this not rebuild the entire overlay _state?.setState(() {}); } } @@ -85,7 +79,7 @@ class OverlayState extends State { OverlayEntry entry = _entries[i]; backwardsChildren.add(new KeyedSubtree( key: new ObjectKey(entry), - child: entry.child + child: entry.builder(context) )); if (entry.opaque) break; diff --git a/packages/flutter/lib/src/widgets/page.dart b/packages/flutter/lib/src/widgets/page.dart index 0aa35a6a401..8833778e8f2 100644 --- a/packages/flutter/lib/src/widgets/page.dart +++ b/packages/flutter/lib/src/widgets/page.dart @@ -105,7 +105,7 @@ class PageRoute extends ModalRoute { String get name => settings.name; Duration get transitionDuration => const Duration(milliseconds: 150); - Widget createModalWidget() => new _Page(key: pageKey, route: this); + Widget buildModalWidget(BuildContext context) => new _Page(key: pageKey, route: this); final PageStorageBucket _storageBucket = new PageStorageBucket(); diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index 41a4f565410..0d4d9ed1fff 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -25,15 +25,14 @@ class StateRoute extends Route { } class OverlayRoute extends Route { - List createWidgets() => const []; + List get builders => const []; List get overlayEntries => _overlayEntries; final List _overlayEntries = new List(); void didPush(OverlayState overlay, OverlayEntry insertionPoint) { - List widgets = createWidgets(); - for (Widget widget in widgets) { - _overlayEntries.add(new OverlayEntry(child: widget)); + for (WidgetBuilder builder in builders) { + _overlayEntries.add(new OverlayEntry(builder: builder)); overlay?.insert(_overlayEntries.last, above: insertionPoint); insertionPoint = _overlayEntries.last; } diff --git a/packages/unit/test/widget/heroes_test.dart b/packages/unit/test/widget/heroes_test.dart index a8dec7a8eea..92aa348a2e7 100644 --- a/packages/unit/test/widget/heroes_test.dart +++ b/packages/unit/test/widget/heroes_test.dart @@ -4,7 +4,8 @@ import 'package:test/test.dart'; import 'widget_tester.dart'; class TestOverlayRoute extends OverlayRoute { - List createWidgets() => [ new Text('Overlay') ]; + List get builders => [ _build ]; + Widget _build(BuildContext context) => new Text('Overlay'); } bool _isOnStage(Element element) {