Unverified Commit aba0379d authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Clean up the existing Navigator API. (#15718)

This is not a grand refactor yet, it's just cleaning up what we have
already, so that people who keep using this API (e.g. dialogs) have
something coherent to deal with.

The major changes are that Navigator and NavigatorState have the same
API now, that most of the examples use `<void>` instead of `<Null>`,
that the navigator observer can see replaces, and that the `settings`
is moved from ModalRoute to Route. I also cleaned up some of the API
documentation.
parent 3a2e0d93
...@@ -47,37 +47,37 @@ class _HomeState extends State<Home> { ...@@ -47,37 +47,37 @@ class _HomeState extends State<Home> {
child: const Text('Test Underlines'), child: const Text('Test Underlines'),
color: Colors.red.shade800, color: Colors.red.shade800,
textColor: Colors.white, textColor: Colors.white,
onPressed: () { Navigator.of(context).pushNamed('underlines'); }, onPressed: () { Navigator.pushNamed(context, 'underlines'); },
), ),
new FlatButton( new FlatButton(
child: const Text('Test Font Fallback'), child: const Text('Test Font Fallback'),
color: Colors.orange.shade700, color: Colors.orange.shade700,
textColor: Colors.white, textColor: Colors.white,
onPressed: () { Navigator.of(context).pushNamed('fallback'); }, onPressed: () { Navigator.pushNamed(context, 'fallback'); },
), ),
new FlatButton( new FlatButton(
child: const Text('Test Bidi Formatting'), child: const Text('Test Bidi Formatting'),
color: Colors.yellow.shade700, color: Colors.yellow.shade700,
textColor: Colors.black, textColor: Colors.black,
onPressed: () { Navigator.of(context).pushNamed('bidi'); }, onPressed: () { Navigator.pushNamed(context, 'bidi'); },
), ),
new FlatButton( new FlatButton(
child: const Text('TextSpan Fuzzer'), child: const Text('TextSpan Fuzzer'),
color: Colors.green.shade400, color: Colors.green.shade400,
textColor: Colors.black, textColor: Colors.black,
onPressed: () { Navigator.of(context).pushNamed('fuzzer'); }, onPressed: () { Navigator.pushNamed(context, 'fuzzer'); },
), ),
new FlatButton( new FlatButton(
child: const Text('Diacritics Fuzzer'), child: const Text('Diacritics Fuzzer'),
color: Colors.blue.shade400, color: Colors.blue.shade400,
textColor: Colors.white, textColor: Colors.white,
onPressed: () { Navigator.of(context).pushNamed('zalgo'); }, onPressed: () { Navigator.pushNamed(context, 'zalgo'); },
), ),
new FlatButton( new FlatButton(
child: const Text('Painting Fuzzer'), child: const Text('Painting Fuzzer'),
color: Colors.purple.shade200, color: Colors.purple.shade200,
textColor: Colors.black, textColor: Colors.black,
onPressed: () { Navigator.of(context).pushNamed('painting'); }, onPressed: () { Navigator.pushNamed(context, 'painting'); },
), ),
], ],
), ),
......
...@@ -451,7 +451,7 @@ class _AnimationDemoHomeState extends State<AnimationDemoHome> { ...@@ -451,7 +451,7 @@ class _AnimationDemoHomeState extends State<AnimationDemoHome> {
if (_scrollController.offset >= midScrollOffset) if (_scrollController.offset >= midScrollOffset)
_scrollController.animateTo(0.0, curve: _kScrollCurve, duration: _kScrollDuration); _scrollController.animateTo(0.0, curve: _kScrollCurve, duration: _kScrollDuration);
else else
Navigator.of(context).maybePop(); Navigator.maybePop(context);
} }
// Only enable paging for the heading when the user has scrolled to midScrollOffset. // Only enable paging for the heading when the user has scrolled to midScrollOffset.
......
...@@ -21,7 +21,7 @@ class _CupertinoDialogDemoState extends State<CupertinoDialogDemo> { ...@@ -21,7 +21,7 @@ class _CupertinoDialogDemoState extends State<CupertinoDialogDemo> {
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) => child, builder: (BuildContext context) => child,
) )
.then<Null>((T value) { // The value passed to Navigator.pop() or null. .then<void>((T value) { // The value passed to Navigator.pop() or null.
if (value != null) { if (value != null) {
_scaffoldKey.currentState.showSnackBar(new SnackBar( _scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('You selected: $value') content: new Text('You selected: $value')
......
...@@ -173,7 +173,7 @@ class Tab1RowItem extends StatelessWidget { ...@@ -173,7 +173,7 @@ class Tab1RowItem extends StatelessWidget {
final Widget row = new GestureDetector( final Widget row = new GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
Navigator.of(context).push(new CupertinoPageRoute<Null>( Navigator.of(context).push(new CupertinoPageRoute<void>(
builder: (BuildContext context) => new Tab1ItemPage( builder: (BuildContext context) => new Tab1ItemPage(
color: color, color: color,
colorName: colorName, colorName: colorName,
...@@ -778,7 +778,7 @@ class Tab3Dialog extends StatelessWidget { ...@@ -778,7 +778,7 @@ class Tab3Dialog extends StatelessWidget {
color: CupertinoColors.activeBlue, color: CupertinoColors.activeBlue,
child: const Text('Sign in'), child: const Text('Sign in'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.pop(context);
}, },
), ),
], ],
......
...@@ -112,7 +112,7 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> { ...@@ -112,7 +112,7 @@ class _CupertinoPickerDemoState extends State<CupertinoPickerDemo> {
const Padding(padding: const EdgeInsets.only(top: 32.0)), const Padding(padding: const EdgeInsets.only(top: 32.0)),
new GestureDetector( new GestureDetector(
onTap: () async { onTap: () async {
await showModalBottomSheet<Null>( await showModalBottomSheet<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return _buildBottomPicker(); return _buildBottomPicker();
......
...@@ -70,7 +70,7 @@ class DialogDemoState extends State<DialogDemo> { ...@@ -70,7 +70,7 @@ class DialogDemoState extends State<DialogDemo> {
context: context, context: context,
builder: (BuildContext context) => child, builder: (BuildContext context) => child,
) )
.then<Null>((T value) { // The value passed to Navigator.pop() or null. .then<void>((T value) { // The value passed to Navigator.pop() or null.
if (value != null) { if (value != null) {
_scaffoldKey.currentState.showSnackBar(new SnackBar( _scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('You selected: $value') content: new Text('You selected: $value')
......
...@@ -67,7 +67,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin { ...@@ -67,7 +67,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
} }
void _showNotImplementedMessage() { void _showNotImplementedMessage() {
Navigator.of(context).pop(); // Dismiss the drawer. Navigator.pop(context); // Dismiss the drawer.
_scaffoldKey.currentState.showSnackBar(const SnackBar( _scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text("The drawer's items don't do anything") content: const Text("The drawer's items don't do anything")
)); ));
...@@ -231,7 +231,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin { ...@@ -231,7 +231,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
} }
void _onOtherAccountsTap(BuildContext context) { void _onOtherAccountsTap(BuildContext context) {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new AlertDialog( return new AlertDialog(
...@@ -240,7 +240,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin { ...@@ -240,7 +240,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
new FlatButton( new FlatButton(
child: const Text('OK'), child: const Text('OK'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.pop(context);
}, },
), ),
], ],
......
...@@ -165,7 +165,7 @@ class GridDemoPhotoItem extends StatelessWidget { ...@@ -165,7 +165,7 @@ class GridDemoPhotoItem extends StatelessWidget {
final BannerTapCallback onBannerTap; // User taps on the photo's header or footer. final BannerTapCallback onBannerTap; // User taps on the photo's header or footer.
void showPhoto(BuildContext context) { void showPhoto(BuildContext context) {
Navigator.push(context, new MaterialPageRoute<Null>( Navigator.push(context, new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Scaffold( return new Scaffold(
appBar: new AppBar( appBar: new AppBar(
......
...@@ -15,7 +15,7 @@ class ModalBottomSheetDemo extends StatelessWidget { ...@@ -15,7 +15,7 @@ class ModalBottomSheetDemo extends StatelessWidget {
child: new RaisedButton( child: new RaisedButton(
child: const Text('SHOW BOTTOM SHEET'), child: const Text('SHOW BOTTOM SHEET'),
onPressed: () { onPressed: () {
showModalBottomSheet<Null>(context: context, builder: (BuildContext context) { showModalBottomSheet<void>(context: context, builder: (BuildContext context) {
return new Container( return new Container(
child: new Padding( child: new Padding(
padding: const EdgeInsets.all(32.0), padding: const EdgeInsets.all(32.0),
......
...@@ -54,7 +54,7 @@ class _PersistentBottomSheetDemoState extends State<PersistentBottomSheetDemo> { ...@@ -54,7 +54,7 @@ class _PersistentBottomSheetDemoState extends State<PersistentBottomSheetDemo> {
} }
void _showMessage() { void _showMessage() {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new AlertDialog( return new AlertDialog(
......
...@@ -167,14 +167,14 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -167,14 +167,14 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
} }
void showFavoritesPage(BuildContext context) { void showFavoritesPage(BuildContext context) {
Navigator.push(context, new MaterialPageRoute<Null>( Navigator.push(context, new MaterialPageRoute<void>(
settings: const RouteSettings(name: '/pesto/favorites'), settings: const RouteSettings(name: '/pesto/favorites'),
builder: (BuildContext context) => new PestoFavorites(), builder: (BuildContext context) => new PestoFavorites(),
)); ));
} }
void showRecipePage(BuildContext context, Recipe recipe) { void showRecipePage(BuildContext context, Recipe recipe) {
Navigator.push(context, new MaterialPageRoute<Null>( Navigator.push(context, new MaterialPageRoute<void>(
settings: const RouteSettings(name: '/pesto/recipe'), settings: const RouteSettings(name: '/pesto/recipe'),
builder: (BuildContext context) { builder: (BuildContext context) {
return new Theme( return new Theme(
......
...@@ -327,7 +327,7 @@ class ShrineOrderRoute extends ShrinePageRoute<Order> { ...@@ -327,7 +327,7 @@ class ShrineOrderRoute extends ShrinePageRoute<Order> {
ShrineOrderRoute({ ShrineOrderRoute({
@required this.order, @required this.order,
WidgetBuilder builder, WidgetBuilder builder,
RouteSettings settings: const RouteSettings(), RouteSettings settings,
}) : assert(order != null), }) : assert(order != null),
super(builder: builder, settings: settings); super(builder: builder, settings: settings);
...@@ -336,5 +336,5 @@ class ShrineOrderRoute extends ShrinePageRoute<Order> { ...@@ -336,5 +336,5 @@ class ShrineOrderRoute extends ShrinePageRoute<Order> {
@override @override
Order get currentResult => order; Order get currentResult => order;
static ShrineOrderRoute of(BuildContext context) => ModalRoute.of(context); static ShrineOrderRoute of(BuildContext context) => ModalRoute.of<Order>(context);
} }
...@@ -51,7 +51,7 @@ class ShrinePageState extends State<ShrinePage> { ...@@ -51,7 +51,7 @@ class ShrinePageState extends State<ShrinePage> {
} }
void _showShoppingCart() { void _showShoppingCart() {
showModalBottomSheet<Null>(context: context, builder: (BuildContext context) { showModalBottomSheet<void>(context: context, builder: (BuildContext context) {
if (widget.shoppingCart.isEmpty) { if (widget.shoppingCart.isEmpty) {
return const Padding( return const Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
......
...@@ -25,7 +25,7 @@ Widget buildShrine(BuildContext context, Widget child) { ...@@ -25,7 +25,7 @@ Widget buildShrine(BuildContext context, Widget child) {
class ShrinePageRoute<T> extends MaterialPageRoute<T> { class ShrinePageRoute<T> extends MaterialPageRoute<T> {
ShrinePageRoute({ ShrinePageRoute({
WidgetBuilder builder, WidgetBuilder builder,
RouteSettings settings: const RouteSettings() RouteSettings settings,
}) : super(builder: builder, settings: settings); }) : super(builder: builder, settings: settings);
@override @override
......
...@@ -64,12 +64,12 @@ class VideoCard extends StatelessWidget { ...@@ -64,12 +64,12 @@ class VideoCard extends StatelessWidget {
} }
void pushFullScreenWidget() { void pushFullScreenWidget() {
final TransitionRoute<Null> route = new PageRouteBuilder<Null>( final TransitionRoute<void> route = new PageRouteBuilder<void>(
settings: new RouteSettings(name: title, isInitialRoute: false), settings: new RouteSettings(name: title, isInitialRoute: false),
pageBuilder: fullScreenRoutePageBuilder, pageBuilder: fullScreenRoutePageBuilder,
); );
route.completed.then((Null _) { route.completed.then((void result) {
controller.setVolume(0.0); controller.setVolume(0.0);
}); });
......
...@@ -165,7 +165,7 @@ class GalleryAppState extends State<GalleryApp> { ...@@ -165,7 +165,7 @@ class GalleryAppState extends State<GalleryApp> {
checkerboardRasterCacheImages: _checkerboardRasterCacheImages, checkerboardRasterCacheImages: _checkerboardRasterCacheImages,
checkerboardOffscreenLayers: _checkerboardOffscreenLayers, checkerboardOffscreenLayers: _checkerboardOffscreenLayers,
routes: _kRoutes, routes: _kRoutes,
home: _applyScaleFactor(home), home: home,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
return new Directionality( return new Directionality(
textDirection: _overrideDirection, textDirection: _overrideDirection,
......
...@@ -31,23 +31,23 @@ class UpdaterState extends State<Updater> { ...@@ -31,23 +31,23 @@ class UpdaterState extends State<Updater> {
} }
static DateTime _lastUpdateCheck; static DateTime _lastUpdateCheck;
Future<Null> _checkForUpdates() async { Future<void> _checkForUpdates() async {
// Only prompt once a day // Only prompt once a day
if (_lastUpdateCheck != null && if (_lastUpdateCheck != null &&
new DateTime.now().difference(_lastUpdateCheck) < const Duration(days: 1)) { new DateTime.now().difference(_lastUpdateCheck) < const Duration(days: 1)) {
return; // We already checked for updates recently return null; // We already checked for updates recently
} }
_lastUpdateCheck = new DateTime.now(); _lastUpdateCheck = new DateTime.now();
final String updateUrl = await widget.updateUrlFetcher(); final String updateUrl = await widget.updateUrlFetcher();
if (updateUrl != null) { if (updateUrl != null) {
final bool wantsUpdate = await showDialog(context: context, builder: _buildDialog); final bool wantsUpdate = await showDialog<bool>(context: context, builder: _buildDialog);
if (wantsUpdate != null && wantsUpdate) if (wantsUpdate != null && wantsUpdate)
launch(updateUrl); launch(updateUrl);
} }
} }
Widget _buildDialog(BuildContext _) { Widget _buildDialog(BuildContext context) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final TextStyle dialogTextStyle = final TextStyle dialogTextStyle =
theme.textTheme.subhead.copyWith(color: theme.textTheme.caption.color); theme.textTheme.subhead.copyWith(color: theme.textTheme.caption.color);
...@@ -56,16 +56,19 @@ class UpdaterState extends State<Updater> { ...@@ -56,16 +56,19 @@ class UpdaterState extends State<Updater> {
content: new Text('A newer version is available.', style: dialogTextStyle), content: new Text('A newer version is available.', style: dialogTextStyle),
actions: <Widget>[ actions: <Widget>[
new FlatButton( new FlatButton(
child: const Text('NO THANKS'), child: const Text('NO THANKS'),
onPressed: () { onPressed: () {
Navigator.pop(context, false); Navigator.pop(context, false);
}), },
),
new FlatButton( new FlatButton(
child: const Text('UPDATE'), child: const Text('UPDATE'),
onPressed: () { onPressed: () {
Navigator.pop(context, true); Navigator.pop(context, true);
}), },
]); ),
],
);
} }
@override @override
......
...@@ -83,7 +83,7 @@ class StocksAppState extends State<StocksApp> { ...@@ -83,7 +83,7 @@ class StocksAppState extends State<StocksApp> {
return null; return null;
} }
Route<Null> _getRoute(RouteSettings settings) { Route<dynamic> _getRoute(RouteSettings settings) {
// Routes, by convention, are split on slashes, like filesystem paths. // Routes, by convention, are split on slashes, like filesystem paths.
final List<String> path = settings.name.split('/'); final List<String> path = settings.name.split('/');
// We only support paths that start with a slash, so bail if // We only support paths that start with a slash, so bail if
...@@ -100,7 +100,7 @@ class StocksAppState extends State<StocksApp> { ...@@ -100,7 +100,7 @@ class StocksAppState extends State<StocksApp> {
// Extract the symbol part of "stock:..." and return a route // Extract the symbol part of "stock:..." and return a route
// for that symbol. // for that symbol.
final String symbol = path[1].substring(6); final String symbol = path[1].substring(6);
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => new StockSymbolPage(symbol: symbol, stocks: stocks), builder: (BuildContext context) => new StockSymbolPage(symbol: symbol, stocks: stocks),
); );
......
...@@ -93,7 +93,7 @@ class StockHomeState extends State<StockHome> { ...@@ -93,7 +93,7 @@ class StockHomeState extends State<StockHome> {
}); });
break; break;
case _StockMenuItem.refresh: case _StockMenuItem.refresh:
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) => new _NotImplementedDialog(), builder: (BuildContext context) => new _NotImplementedDialog(),
); );
...@@ -297,7 +297,7 @@ class StockHomeState extends State<StockHome> { ...@@ -297,7 +297,7 @@ class StockHomeState extends State<StockHome> {
} }
void _handleCreateCompany() { void _handleCreateCompany() {
showModalBottomSheet<Null>( showModalBottomSheet<void>(
context: context, context: context,
builder: (BuildContext context) => new _CreateCompanySheet(), builder: (BuildContext context) => new _CreateCompanySheet(),
); );
......
...@@ -397,7 +397,7 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe ...@@ -397,7 +397,7 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
) )
: const Text('Close'), : const Text('Close'),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { Navigator.of(context).maybePop(); }, onPressed: () { Navigator.maybePop(context); },
); );
} }
} }
......
...@@ -76,16 +76,15 @@ final DecorationTween _kGradientShadowTween = new DecorationTween( ...@@ -76,16 +76,15 @@ final DecorationTween _kGradientShadowTween = new DecorationTween(
class CupertinoPageRoute<T> extends PageRoute<T> { class CupertinoPageRoute<T> extends PageRoute<T> {
/// Creates a page route for use in an iOS designed app. /// Creates a page route for use in an iOS designed app.
/// ///
/// The [builder], [settings], [maintainState], and [fullscreenDialog] /// The [builder], [maintainState], and [fullscreenDialog] arguments must not
/// arguments must not be null. /// be null.
CupertinoPageRoute({ CupertinoPageRoute({
@required this.builder, @required this.builder,
RouteSettings settings: const RouteSettings(), RouteSettings settings,
this.maintainState: true, this.maintainState: true,
bool fullscreenDialog: false, bool fullscreenDialog: false,
this.hostRoute, this.hostRoute,
}) : assert(builder != null), }) : assert(builder != null),
assert(settings != null),
assert(maintainState != null), assert(maintainState != null),
assert(fullscreenDialog != null), assert(fullscreenDialog != null),
super(settings: settings, fullscreenDialog: fullscreenDialog) { super(settings: settings, fullscreenDialog: fullscreenDialog) {
...@@ -149,7 +148,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> { ...@@ -149,7 +148,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
super.dispose(); super.dispose();
} }
_CupertinoBackGestureController _backGestureController; _CupertinoBackGestureController<T> _backGestureController;
/// Whether a pop gesture is currently underway. /// Whether a pop gesture is currently underway.
/// ///
...@@ -217,11 +216,11 @@ class CupertinoPageRoute<T> extends PageRoute<T> { ...@@ -217,11 +216,11 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
/// appropriate. /// appropriate.
/// * [Route.startPopGesture], which describes the contract that this method /// * [Route.startPopGesture], which describes the contract that this method
/// must implement. /// must implement.
_CupertinoBackGestureController _startPopGesture() { _CupertinoBackGestureController<T> _startPopGesture() {
assert(!popGestureInProgress); assert(!popGestureInProgress);
assert(popGestureEnabled); assert(popGestureEnabled);
final PageRoute<T> route = hostRoute ?? this; final PageRoute<T> route = hostRoute ?? this;
_backGestureController = new _CupertinoBackGestureController( _backGestureController = new _CupertinoBackGestureController<T>(
navigator: route.navigator, navigator: route.navigator,
controller: route.controller, controller: route.controller,
onEnded: _endPopGesture, onEnded: _endPopGesture,
...@@ -265,7 +264,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> { ...@@ -265,7 +264,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
// In the middle of a back gesture drag, let the transition be linear to // In the middle of a back gesture drag, let the transition be linear to
// match finger motions. // match finger motions.
linearTransition: popGestureInProgress, linearTransition: popGestureInProgress,
child: new _CupertinoBackGestureDetector( child: new _CupertinoBackGestureDetector<T>(
enabledCallback: () => popGestureEnabled, enabledCallback: () => popGestureEnabled,
onStartPopGesture: _startPopGesture, onStartPopGesture: _startPopGesture,
child: child, child: child,
...@@ -392,7 +391,10 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget { ...@@ -392,7 +391,10 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget {
/// ///
/// The gesture data is converted from absolute coordinates to logical /// The gesture data is converted from absolute coordinates to logical
/// coordinates by this widget. /// coordinates by this widget.
class _CupertinoBackGestureDetector extends StatefulWidget { ///
/// The type `T` specifies the return type of the route with which this gesture
/// detector is associated.
class _CupertinoBackGestureDetector<T> extends StatefulWidget {
const _CupertinoBackGestureDetector({ const _CupertinoBackGestureDetector({
Key key, Key key,
@required this.enabledCallback, @required this.enabledCallback,
...@@ -407,14 +409,14 @@ class _CupertinoBackGestureDetector extends StatefulWidget { ...@@ -407,14 +409,14 @@ class _CupertinoBackGestureDetector extends StatefulWidget {
final ValueGetter<bool> enabledCallback; final ValueGetter<bool> enabledCallback;
final ValueGetter<_CupertinoBackGestureController> onStartPopGesture; final ValueGetter<_CupertinoBackGestureController<T>> onStartPopGesture;
@override @override
_CupertinoBackGestureDetectorState createState() => new _CupertinoBackGestureDetectorState(); _CupertinoBackGestureDetectorState<T> createState() => new _CupertinoBackGestureDetectorState<T>();
} }
class _CupertinoBackGestureDetectorState extends State<_CupertinoBackGestureDetector> { class _CupertinoBackGestureDetectorState<T> extends State<_CupertinoBackGestureDetector<T>> {
_CupertinoBackGestureController _backGestureController; _CupertinoBackGestureController<T> _backGestureController;
HorizontalDragGestureRecognizer _recognizer; HorizontalDragGestureRecognizer _recognizer;
...@@ -508,7 +510,10 @@ class _CupertinoBackGestureDetectorState extends State<_CupertinoBackGestureDete ...@@ -508,7 +510,10 @@ class _CupertinoBackGestureDetectorState extends State<_CupertinoBackGestureDete
/// ///
/// This class works entirely in logical coordinates (0.0 is new page dismissed, /// This class works entirely in logical coordinates (0.0 is new page dismissed,
/// 1.0 is new page on top). /// 1.0 is new page on top).
class _CupertinoBackGestureController { ///
/// The type `T` specifies the return type of the route with which this gesture
/// detector controller is associated.
class _CupertinoBackGestureController<T> {
/// Creates a controller for an iOS-style back gesture. /// Creates a controller for an iOS-style back gesture.
/// ///
/// The [navigator] and [controller] arguments must not be null. /// The [navigator] and [controller] arguments must not be null.
...@@ -566,7 +571,7 @@ class _CupertinoBackGestureController { ...@@ -566,7 +571,7 @@ class _CupertinoBackGestureController {
controller.removeStatusListener(_handleStatusChanged); controller.removeStatusListener(_handleStatusChanged);
_animating = false; _animating = false;
if (status == AnimationStatus.dismissed) if (status == AnimationStatus.dismissed)
navigator.pop(); // this will cause the route to get disposed, which will dispose us navigator.pop<T>(); // this will cause the route to get disposed, which will dispose us
onEnded(); // this will call dispose if popping the route failed to do so onEnded(); // this will call dispose if popping the route failed to do so
} }
......
...@@ -149,9 +149,9 @@ void showAboutDialog({ ...@@ -149,9 +149,9 @@ void showAboutDialog({
String applicationVersion, String applicationVersion,
Widget applicationIcon, Widget applicationIcon,
String applicationLegalese, String applicationLegalese,
List<Widget> children List<Widget> children,
}) { }) {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new AboutDialog( return new AboutDialog(
...@@ -185,9 +185,7 @@ void showLicensePage({ ...@@ -185,9 +185,7 @@ void showLicensePage({
Widget applicationIcon, Widget applicationIcon,
String applicationLegalese String applicationLegalese
}) { }) {
// TODO(ianh): remove pop once https://github.com/flutter/flutter/issues/4667 is fixed Navigator.push(context, new MaterialPageRoute<void>(
Navigator.pop(context);
Navigator.push(context, new MaterialPageRoute<Null>(
builder: (BuildContext context) => new LicensePage( builder: (BuildContext context) => new LicensePage(
applicationName: applicationName, applicationName: applicationName,
applicationVersion: applicationVersion, applicationVersion: applicationVersion,
......
...@@ -607,10 +607,11 @@ class _MaterialAppState extends State<MaterialApp> { ...@@ -607,10 +607,11 @@ class _MaterialAppState extends State<MaterialApp> {
Route<dynamic> _onGenerateRoute(RouteSettings settings) { Route<dynamic> _onGenerateRoute(RouteSettings settings) {
final String name = settings.name; final String name = settings.name;
WidgetBuilder builder; WidgetBuilder builder;
if (name == Navigator.defaultRouteName && widget.home != null) if (name == Navigator.defaultRouteName && widget.home != null) {
builder = (BuildContext context) => widget.home; builder = (BuildContext context) => widget.home;
else } else {
builder = widget.routes[name]; builder = widget.routes[name];
}
if (builder != null) { if (builder != null) {
return new MaterialPageRoute<dynamic>( return new MaterialPageRoute<dynamic>(
builder: builder, builder: builder,
......
...@@ -86,7 +86,7 @@ class BackButton extends StatelessWidget { ...@@ -86,7 +86,7 @@ class BackButton extends StatelessWidget {
color: color, color: color,
tooltip: MaterialLocalizations.of(context).backButtonTooltip, tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () { onPressed: () {
Navigator.of(context).maybePop(); Navigator.maybePop(context);
} }
); );
} }
...@@ -118,7 +118,7 @@ class CloseButton extends StatelessWidget { ...@@ -118,7 +118,7 @@ class CloseButton extends StatelessWidget {
icon: const Icon(Icons.close), icon: const Icon(Icons.close),
tooltip: MaterialLocalizations.of(context).closeButtonTooltip, tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
onPressed: () { onPressed: () {
Navigator.of(context).maybePop(); Navigator.maybePop(context);
}, },
); );
} }
......
...@@ -179,14 +179,10 @@ class _ModalBottomSheet<T> extends StatefulWidget { ...@@ -179,14 +179,10 @@ class _ModalBottomSheet<T> extends StatefulWidget {
} }
class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
void _navigatorPop() {
Navigator.pop(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: _navigatorPop, onTap: () => Navigator.pop(context),
child: new AnimatedBuilder( child: new AnimatedBuilder(
animation: widget.route.animation, animation: widget.route.animation,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
...@@ -211,7 +207,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -211,7 +207,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
this.builder, this.builder,
this.theme, this.theme,
this.barrierLabel, this.barrierLabel,
}); RouteSettings settings,
}) : super(settings: settings);
final WidgetBuilder builder; final WidgetBuilder builder;
final ThemeData theme; final ThemeData theme;
......
...@@ -488,8 +488,10 @@ class _DialogRoute<T> extends PopupRoute<T> { ...@@ -488,8 +488,10 @@ class _DialogRoute<T> extends PopupRoute<T> {
bool barrierDismissible: true, bool barrierDismissible: true,
this.barrierLabel, this.barrierLabel,
@required this.child, @required this.child,
RouteSettings settings,
}) : assert(barrierDismissible != null), }) : assert(barrierDismissible != null),
_barrierDismissible = barrierDismissible; _barrierDismissible = barrierDismissible,
super(settings: settings);
final Widget child; final Widget child;
final ThemeData theme; final ThemeData theme;
......
...@@ -600,7 +600,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi ...@@ -600,7 +600,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
Navigator.push(context, _dropdownRoute).then<void>((_DropdownRouteResult<T> newValue) { Navigator.push(context, _dropdownRoute).then<void>((_DropdownRouteResult<T> newValue) {
_dropdownRoute = null; _dropdownRoute = null;
if (!mounted || newValue == null) if (!mounted || newValue == null)
return null; return;
if (widget.onChanged != null) if (widget.onChanged != null)
widget.onChanged(newValue.result); widget.onChanged(newValue.result);
}); });
......
...@@ -48,34 +48,38 @@ class _MountainViewPageTransition extends StatelessWidget { ...@@ -48,34 +48,38 @@ class _MountainViewPageTransition extends StatelessWidget {
} }
} }
/// A modal route that replaces the entire screen with a platform-adaptive transition. /// A modal route that replaces the entire screen with a platform-adaptive
/// transition.
/// ///
/// For Android, the entrance transition for the page slides the page upwards and fades it /// For Android, the entrance transition for the page slides the page upwards
/// in. The exit transition is the same, but in reverse. /// and fades it in. The exit transition is the same, but in reverse.
/// ///
/// The transition is adaptive to the platform and on iOS, the page slides in from the right and /// The transition is adaptive to the platform and on iOS, the page slides in
/// exits in reverse. The page also shifts to the left in parallax when another page enters to /// from the right and exits in reverse. The page also shifts to the left in
/// cover it. /// parallax when another page enters to cover it. (These directions are flipped
/// in environements with a right-to-left reading direction.)
/// ///
/// By default, when a modal route is replaced by another, the previous route /// By default, when a modal route is replaced by another, the previous route
/// remains in memory. To free all the resources when this is not necessary, set /// remains in memory. To free all the resources when this is not necessary, set
/// [maintainState] to false. /// [maintainState] to false.
/// ///
/// Specify whether the incoming page is a fullscreen modal dialog. On iOS, those /// The `fullscreenDialog` property specifies whether the incoming page is a
/// pages animate bottom->up rather than right->left. /// fullscreen modal dialog. On iOS, those pages animate from the bottom to the
/// top rather than horizontally.
/// ///
/// The type `T` specifies the return type of the route which can be supplied as /// The type `T` specifies the return type of the route which can be supplied as
/// the route is popped from the stack via [Navigator.pop] when an optional /// the route is popped from the stack via [Navigator.pop] by providing the
/// `result` can be provided. /// optional `result` argument.
/// ///
/// See also: /// See also:
/// ///
/// * [CupertinoPageRoute], that this [PageRoute] delegates transition animations to for iOS. /// * [CupertinoPageRoute], which this [PageRoute] delegates transition
/// animations to for iOS.
class MaterialPageRoute<T> extends PageRoute<T> { class MaterialPageRoute<T> extends PageRoute<T> {
/// Creates a page route for use in a material design app. /// Creates a page route for use in a material design app.
MaterialPageRoute({ MaterialPageRoute({
@required this.builder, @required this.builder,
RouteSettings settings: const RouteSettings(), RouteSettings settings,
this.maintainState: true, this.maintainState: true,
bool fullscreenDialog: false, bool fullscreenDialog: false,
}) : assert(builder != null), }) : assert(builder != null),
......
...@@ -196,15 +196,44 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> { ...@@ -196,15 +196,44 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
bool represents(T value) => value == this.value; bool represents(T value) => value == this.value;
@override @override
_PopupMenuItemState<PopupMenuItem<T>> createState() => new _PopupMenuItemState<PopupMenuItem<T>>(); PopupMenuItemState<T, PopupMenuItem<T>> createState() => new PopupMenuItemState<T, PopupMenuItem<T>>();
} }
class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> { /// The [State] for [PopupMenuItem] subclasses.
// Override this to put something else in the menu entry. ///
/// By default this implements the basic styling and layout of Material Design
/// popup menu items.
///
/// The [buildChild] method can be overridden to adjust exactly what gets placed
/// in the menu. By default it returns [PopupMenuItem.child].
///
/// The [handleTap] method can be overridden to adjust exactly what happens when
/// the item is tapped. By default, it uses [Navigator.pop] to return the
/// [PopupMenuItem.value] from the menu route.
///
/// This class takes two type arguments. The second, `W`, is the exact type of
/// the [Widget] that is using this [State]. It must be a subclass of
/// [PopupMenuItem]. The first, `T`, must match the type argument of that widget
/// class, and is the type of values returned from this menu.
class PopupMenuItemState<T, W extends PopupMenuItem<T>> extends State<W> {
/// The menu item contents.
///
/// Used by the [build] method.
///
/// By default, this returns [PopupMenuItem.child]. Override this to put
/// something else in the menu entry.
@protected
Widget buildChild() => widget.child; Widget buildChild() => widget.child;
/// The handler for when the user selects the menu item.
///
/// Used by the [InkWell] inserted by the [build] method.
///
/// By default, uses [Navigator.pop] to return the [PopupMenuItem.value] from
/// the menu route.
@protected
void handleTap() { void handleTap() {
Navigator.pop(context, widget.value); Navigator.pop<T>(context, widget.value);
} }
@override @override
...@@ -238,8 +267,8 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> { ...@@ -238,8 +267,8 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> {
height: widget.height, height: widget.height,
padding: const EdgeInsets.symmetric(horizontal: _kMenuHorizontalPadding), padding: const EdgeInsets.symmetric(horizontal: _kMenuHorizontalPadding),
child: item, child: item,
) ),
) ),
); );
} }
} }
...@@ -349,7 +378,7 @@ class CheckedPopupMenuItem<T> extends PopupMenuItem<T> { ...@@ -349,7 +378,7 @@ class CheckedPopupMenuItem<T> extends PopupMenuItem<T> {
_CheckedPopupMenuItemState<T> createState() => new _CheckedPopupMenuItemState<T>(); _CheckedPopupMenuItemState<T> createState() => new _CheckedPopupMenuItemState<T>();
} }
class _CheckedPopupMenuItemState<T> extends _PopupMenuItemState<CheckedPopupMenuItem<T>> with SingleTickerProviderStateMixin { class _CheckedPopupMenuItemState<T> extends PopupMenuItemState<T, CheckedPopupMenuItem<T>> with SingleTickerProviderStateMixin {
static const Duration _kFadeDuration = const Duration(milliseconds: 150); static const Duration _kFadeDuration = const Duration(milliseconds: 150);
AnimationController _controller; AnimationController _controller;
Animation<double> get _opacity => _controller.view; Animation<double> get _opacity => _controller.view;
......
...@@ -680,6 +680,9 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -680,6 +680,9 @@ class SemanticsProperties extends DiagnosticableTree {
properties.add(new EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(new EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(new DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null)); properties.add(new DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
} }
@override
String toStringShort() => '$runtimeType'; // the hashCode isn't important since we're immutable
} }
/// In tests use this function to reset the counter used to generate /// In tests use this function to reset the counter used to generate
......
...@@ -12,7 +12,7 @@ import 'routes.dart'; ...@@ -12,7 +12,7 @@ import 'routes.dart';
abstract class PageRoute<T> extends ModalRoute<T> { abstract class PageRoute<T> extends ModalRoute<T> {
/// Creates a modal route that replaces the entire screen. /// Creates a modal route that replaces the entire screen.
PageRoute({ PageRoute({
RouteSettings settings: const RouteSettings(), RouteSettings settings,
this.fullscreenDialog: false, this.fullscreenDialog: false,
}) : super(settings: settings); }) : super(settings: settings);
...@@ -71,7 +71,7 @@ class PageRouteBuilder<T> extends PageRoute<T> { ...@@ -71,7 +71,7 @@ class PageRouteBuilder<T> extends PageRoute<T> {
/// The [pageBuilder], [transitionsBuilder], [opaque], [barrierDismissible], /// The [pageBuilder], [transitionsBuilder], [opaque], [barrierDismissible],
/// and [maintainState] arguments must not be null. /// and [maintainState] arguments must not be null.
PageRouteBuilder({ PageRouteBuilder({
RouteSettings settings: const RouteSettings(), RouteSettings settings,
@required this.pageBuilder, @required this.pageBuilder,
this.transitionsBuilder: _defaultTransitionsBuilder, this.transitionsBuilder: _defaultTransitionsBuilder,
this.transitionDuration: const Duration(milliseconds: 300), this.transitionDuration: const Duration(milliseconds: 300),
......
...@@ -17,7 +17,7 @@ void main() { ...@@ -17,7 +17,7 @@ void main() {
builder: (BuildContext context) { builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoAlertDialog( return new CupertinoAlertDialog(
...@@ -110,7 +110,7 @@ void main() { ...@@ -110,7 +110,7 @@ void main() {
child: new Builder(builder: (BuildContext context) { child: new Builder(builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new MediaQuery( return new MediaQuery(
......
...@@ -14,7 +14,7 @@ void main() { ...@@ -14,7 +14,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -36,7 +36,7 @@ void main() { ...@@ -36,7 +36,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -56,7 +56,7 @@ void main() { ...@@ -56,7 +56,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -76,7 +76,7 @@ void main() { ...@@ -76,7 +76,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -98,7 +98,7 @@ void main() { ...@@ -98,7 +98,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoPageScaffold( return const CupertinoPageScaffold(
...@@ -126,7 +126,7 @@ void main() { ...@@ -126,7 +126,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new MediaQuery( return new MediaQuery(
...@@ -178,7 +178,7 @@ void main() { ...@@ -178,7 +178,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoPageScaffold( return new CupertinoPageScaffold(
...@@ -266,7 +266,7 @@ void main() { ...@@ -266,7 +266,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoPageScaffold( return new CupertinoPageScaffold(
...@@ -337,7 +337,7 @@ void main() { ...@@ -337,7 +337,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -351,7 +351,7 @@ void main() { ...@@ -351,7 +351,7 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
middle: const Text('Page 2'), middle: const Text('Page 2'),
...@@ -365,7 +365,7 @@ void main() { ...@@ -365,7 +365,7 @@ void main() {
expect(find.byType(CupertinoButton), findsOneWidget); expect(find.byType(CupertinoButton), findsOneWidget);
expect(find.byType(Icon), findsOneWidget); expect(find.byType(Icon), findsOneWidget);
tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -401,7 +401,7 @@ void main() { ...@@ -401,7 +401,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -428,7 +428,7 @@ void main() { ...@@ -428,7 +428,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
...@@ -462,7 +462,7 @@ void main() { ...@@ -462,7 +462,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoNavigationBar( return const CupertinoNavigationBar(
......
...@@ -11,7 +11,7 @@ void main() { ...@@ -11,7 +11,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
final String pageNumber = settings.name == '/' ? '1' : '2'; final String pageNumber = settings.name == '/' ? '1' : '2';
...@@ -82,7 +82,7 @@ void main() { ...@@ -82,7 +82,7 @@ void main() {
], ],
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
final String pageNumber = settings.name == '/' ? '1' : '2'; final String pageNumber = settings.name == '/' ? '1' : '2';
...@@ -151,7 +151,7 @@ void main() { ...@@ -151,7 +151,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const Center(child: const Text('Page 1')); return const Center(child: const Text('Page 1'));
...@@ -163,7 +163,7 @@ void main() { ...@@ -163,7 +163,7 @@ void main() {
final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1')); final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1'));
tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return const Center(child: const Text('Page 2')); return const Center(child: const Text('Page 2'));
}, },
...@@ -219,7 +219,7 @@ void main() { ...@@ -219,7 +219,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
final String pageNumber = settings.name == '/' ? '1' : '2'; final String pageNumber = settings.name == '/' ? '1' : '2';
...@@ -284,7 +284,7 @@ void main() { ...@@ -284,7 +284,7 @@ void main() {
], ],
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
final String pageNumber = settings.name == '/' ? '1' : '2'; final String pageNumber = settings.name == '/' ? '1' : '2';
......
...@@ -14,7 +14,7 @@ void main() { ...@@ -14,7 +14,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoPageScaffold( return const CupertinoPageScaffold(
...@@ -40,7 +40,7 @@ void main() { ...@@ -40,7 +40,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabScaffold( return new CupertinoTabScaffold(
...@@ -85,7 +85,7 @@ void main() { ...@@ -85,7 +85,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new MediaQuery( return new MediaQuery(
...@@ -145,7 +145,7 @@ void main() { ...@@ -145,7 +145,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabScaffold( return new CupertinoTabScaffold(
...@@ -175,7 +175,7 @@ void main() { ...@@ -175,7 +175,7 @@ void main() {
child: const Text('Next'), child: const Text('Next'),
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
new CupertinoPageRoute<Null>( new CupertinoPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoPageScaffold( return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar( navigationBar: new CupertinoNavigationBar(
...@@ -260,7 +260,7 @@ void main() { ...@@ -260,7 +260,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoPageScaffold( return const CupertinoPageScaffold(
...@@ -284,7 +284,7 @@ void main() { ...@@ -284,7 +284,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const CupertinoPageScaffold( return const CupertinoPageScaffold(
......
...@@ -23,7 +23,7 @@ void main() { ...@@ -23,7 +23,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabScaffold( return new CupertinoTabScaffold(
...@@ -85,7 +85,7 @@ void main() { ...@@ -85,7 +85,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabScaffold( return new CupertinoTabScaffold(
...@@ -129,7 +129,7 @@ void main() { ...@@ -129,7 +129,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabScaffold( return new CupertinoTabScaffold(
...@@ -171,7 +171,7 @@ void main() { ...@@ -171,7 +171,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
......
...@@ -11,7 +11,7 @@ void main() { ...@@ -11,7 +11,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabView( return new CupertinoTabView(
...@@ -31,7 +31,7 @@ void main() { ...@@ -31,7 +31,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabView( return new CupertinoTabView(
...@@ -53,7 +53,7 @@ void main() { ...@@ -53,7 +53,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabView( return new CupertinoTabView(
...@@ -87,13 +87,13 @@ void main() { ...@@ -87,13 +87,13 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabView( return new CupertinoTabView(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
if (settings.name == Navigator.defaultRouteName) { if (settings.name == Navigator.defaultRouteName) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return const Text('generated home'); return const Text('generated home');
...@@ -117,7 +117,7 @@ void main() { ...@@ -117,7 +117,7 @@ void main() {
new WidgetsApp( new WidgetsApp(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new CupertinoPageRoute<Null>( return new CupertinoPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new CupertinoTabView( return new CupertinoTabView(
......
...@@ -87,7 +87,7 @@ void main() { ...@@ -87,7 +87,7 @@ void main() {
expect(state2.marker, equals('original')); expect(state2.marker, equals('original'));
}); });
testWidgets('Do not rebuild page on the second frame of the route transition', (WidgetTester tester) async { testWidgets('Do not rebuild page during a route transition', (WidgetTester tester) async {
int buildCounter = 0; int buildCounter = 0;
await tester.pumpWidget( await tester.pumpWidget(
new MaterialApp( new MaterialApp(
...@@ -128,10 +128,82 @@ void main() { ...@@ -128,10 +128,82 @@ void main() {
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
expect(buildCounter, 1); expect(buildCounter, 1);
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(buildCounter, 2); expect(buildCounter, 1);
expect(find.text('Y'), findsOneWidget); expect(find.text('Y'), findsOneWidget);
}); });
testWidgets('Do rebuild the home page if it changes', (WidgetTester tester) async {
int buildCounter = 0;
await tester.pumpWidget(
new MaterialApp(
home: new Builder(
builder: (BuildContext context) {
++buildCounter;
return const Text('A');
}
),
),
);
expect(buildCounter, 1);
expect(find.text('A'), findsOneWidget);
await tester.pumpWidget(
new MaterialApp(
home: new Builder(
builder: (BuildContext context) {
++buildCounter;
return const Text('B');
}
),
),
);
expect(buildCounter, 2);
expect(find.text('B'), findsOneWidget);
});
testWidgets('Do not rebuild the home page if it does not actually change', (WidgetTester tester) async {
int buildCounter = 0;
final Widget home = new Builder(
builder: (BuildContext context) {
++buildCounter;
return const Placeholder();
}
);
await tester.pumpWidget(
new MaterialApp(
home: home,
),
);
expect(buildCounter, 1);
await tester.pumpWidget(
new MaterialApp(
home: home,
),
);
expect(buildCounter, 1);
});
testWidgets('Do rebuild pages that come from the routes table if the MaterialApp changes', (WidgetTester tester) async {
int buildCounter = 0;
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) {
++buildCounter;
return const Placeholder();
},
};
await tester.pumpWidget(
new MaterialApp(
routes: routes,
),
);
expect(buildCounter, 1);
await tester.pumpWidget(
new MaterialApp(
routes: routes,
),
);
expect(buildCounter, 2);
});
testWidgets('Cannot pop the initial route', (WidgetTester tester) async { testWidgets('Cannot pop the initial route', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp(home: const Text('Home'))); await tester.pumpWidget(new MaterialApp(home: const Text('Home')));
......
...@@ -21,7 +21,7 @@ void main() { ...@@ -21,7 +21,7 @@ void main() {
child: new RaisedButton( child: new RaisedButton(
child: const Text('X'), child: const Text('X'),
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new AlertDialog( return new AlertDialog(
...@@ -71,7 +71,7 @@ void main() { ...@@ -71,7 +71,7 @@ void main() {
child: new RaisedButton( child: new RaisedButton(
child: const Text('X'), child: const Text('X'),
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return const AlertDialog( return const AlertDialog(
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
final BuildContext context = tester.element(find.text('Go')); final BuildContext context = tester.element(find.text('Go'));
final Future<int> result = showDialog( final Future<int> result = showDialog<int>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new SimpleDialog( return new SimpleDialog(
...@@ -161,7 +161,7 @@ void main() { ...@@ -161,7 +161,7 @@ void main() {
final BuildContext context = tester.element(find.text('Go')); final BuildContext context = tester.element(find.text('Go'));
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return new Container( return new Container(
...@@ -182,7 +182,7 @@ void main() { ...@@ -182,7 +182,7 @@ void main() {
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
expect(find.text('Dialog1'), findsNothing); expect(find.text('Dialog1'), findsNothing);
showDialog<Null>( showDialog<void>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) { builder: (BuildContext context) {
...@@ -227,7 +227,7 @@ void main() { ...@@ -227,7 +227,7 @@ void main() {
final BuildContext context = tester.element(find.text(buttonText)); final BuildContext context = tester.element(find.text(buttonText));
const String alertText = 'A button in an overlay alert'; const String alertText = 'A button in an overlay alert';
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return const AlertDialog(title: const Text(alertText)); return const AlertDialog(title: const Text(alertText));
...@@ -260,7 +260,7 @@ void main() { ...@@ -260,7 +260,7 @@ void main() {
), ),
child: new Navigator( child: new Navigator(
onGenerateRoute: (_) { onGenerateRoute: (_) {
return new PageRouteBuilder<Null>( return new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
outerContext = context; outerContext = context;
return new Container(); return new Container();
...@@ -271,7 +271,7 @@ void main() { ...@@ -271,7 +271,7 @@ void main() {
), ),
)); ));
showDialog<Null>( showDialog<void>(
context: outerContext, context: outerContext,
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) { builder: (BuildContext context) {
......
...@@ -76,7 +76,7 @@ class _TestAppState extends State<TestApp> { ...@@ -76,7 +76,7 @@ class _TestAppState extends State<TestApp> {
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
assert(settings.name == '/'); assert(settings.name == '/');
return new MaterialPageRoute<dynamic>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => widget.child, builder: (BuildContext context) => widget.child,
); );
...@@ -159,7 +159,7 @@ void main() { ...@@ -159,7 +159,7 @@ void main() {
child: new Navigator( child: new Navigator(
initialRoute: '/', initialRoute: '/',
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
......
...@@ -84,7 +84,7 @@ void main() { ...@@ -84,7 +84,7 @@ void main() {
), ),
), ),
); );
Navigator.push(theContext, new PageRouteBuilder<Null>( Navigator.push(theContext, new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return const Placeholder(); return const Placeholder();
}, },
...@@ -107,7 +107,7 @@ void main() { ...@@ -107,7 +107,7 @@ void main() {
), ),
), ),
); );
Navigator.push(theContext, new PageRouteBuilder<Null>( Navigator.push(theContext, new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return const Placeholder(); return const Placeholder();
}, },
...@@ -131,7 +131,7 @@ void main() { ...@@ -131,7 +131,7 @@ void main() {
), ),
), ),
); );
Navigator.push(theContext, new PageRouteBuilder<Null>( Navigator.push(theContext, new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return const Placeholder(); return const Placeholder();
}, },
......
...@@ -27,7 +27,7 @@ void main() { ...@@ -27,7 +27,7 @@ void main() {
showModalBottomSheet<Null>( showModalBottomSheet<Null>(
context: savedContext, context: savedContext,
builder: (BuildContext context) => const Text('BottomSheet') builder: (BuildContext context) => const Text('BottomSheet')
).then<Null>((Null result) { ).then<void>((Null result) {
expectSync(result, isNull); expectSync(result, isNull);
showBottomSheetThenCalled = true; showBottomSheetThenCalled = true;
}); });
...@@ -49,7 +49,7 @@ void main() { ...@@ -49,7 +49,7 @@ void main() {
showModalBottomSheet<Null>( showModalBottomSheet<Null>(
context: savedContext, context: savedContext,
builder: (BuildContext context) => const Text('BottomSheet'), builder: (BuildContext context) => const Text('BottomSheet'),
).then<Null>((Null result) { ).then<void>((Null result) {
expectSync(result, isNull); expectSync(result, isNull);
showBottomSheetThenCalled = true; showBottomSheetThenCalled = true;
}); });
...@@ -172,7 +172,7 @@ void main() { ...@@ -172,7 +172,7 @@ void main() {
), ),
child: new Navigator( child: new Navigator(
onGenerateRoute: (_) { onGenerateRoute: (_) {
return new PageRouteBuilder<Null>( return new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
outerContext = context; outerContext = context;
return new Container(); return new Container();
...@@ -184,7 +184,7 @@ void main() { ...@@ -184,7 +184,7 @@ void main() {
), ),
)); ));
showModalBottomSheet<Null>( showModalBottomSheet<void>(
context: outerContext, context: outerContext,
builder: (BuildContext context) { builder: (BuildContext context) {
innerContext = context; innerContext = context;
......
...@@ -156,7 +156,7 @@ void main() { ...@@ -156,7 +156,7 @@ void main() {
final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1')); final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1'));
tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return const Material(child: const Text('Page 2')); return const Material(child: const Text('Page 2'));
}, },
...@@ -355,7 +355,7 @@ void main() { ...@@ -355,7 +355,7 @@ void main() {
) )
); );
tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return const Scaffold(body: const Text('Page 2')); return const Scaffold(body: const Text('Page 2'));
}, },
......
...@@ -453,7 +453,7 @@ class _TestAppState extends State<TestApp> { ...@@ -453,7 +453,7 @@ class _TestAppState extends State<TestApp> {
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
assert(settings.name == '/'); assert(settings.name == '/');
return new MaterialPageRoute<dynamic>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => new Material( builder: (BuildContext context) => new Material(
child: widget.child, child: widget.child,
......
...@@ -419,7 +419,7 @@ void main() { ...@@ -419,7 +419,7 @@ void main() {
) )
); );
tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<Null>( tester.state<NavigatorState>(find.byType(Navigator)).push(new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Scaffold(appBar: new AppBar(), body: const Text('Page 2')); return new Scaffold(appBar: new AppBar(), body: const Text('Page 2'));
}, },
......
...@@ -108,7 +108,7 @@ void main() { ...@@ -108,7 +108,7 @@ void main() {
final BuildContext context = tester.element(find.byType(TextField)); final BuildContext context = tester.element(find.byType(TextField));
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) => const SimpleDialog(title: const Text('Dialog')), builder: (BuildContext context) => const SimpleDialog(title: const Text('Dialog')),
); );
......
...@@ -161,7 +161,7 @@ void main() { ...@@ -161,7 +161,7 @@ void main() {
builder: (BuildContext context) { builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
onPressed: () { onPressed: () {
showModalBottomSheet<Null>( showModalBottomSheet<void>(
context: context, context: context,
builder: (BuildContext context) => const Text('bottomSheet'), builder: (BuildContext context) => const Text('bottomSheet'),
); );
...@@ -198,7 +198,7 @@ void main() { ...@@ -198,7 +198,7 @@ void main() {
builder: (BuildContext context) { builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) => const Text('dialog'), builder: (BuildContext context) => const Text('dialog'),
); );
...@@ -230,7 +230,7 @@ void main() { ...@@ -230,7 +230,7 @@ void main() {
builder: (BuildContext context) { builder: (BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: () { onTap: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return const Scaffold( return const Scaffold(
......
...@@ -240,7 +240,7 @@ void _tests() { ...@@ -240,7 +240,7 @@ void _tests() {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<dynamic>(builder: (BuildContext context) { return new MaterialPageRoute<void>(builder: (BuildContext context) {
return new FlatButton( return new FlatButton(
onPressed: () { onPressed: () {
showTimePicker(context: context, initialTime: initialTime); showTimePicker(context: context, initialTime: initialTime);
......
...@@ -543,7 +543,7 @@ void main() { ...@@ -543,7 +543,7 @@ void main() {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<dynamic>( return new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Center( return new Center(
child: new Tooltip( child: new Tooltip(
......
...@@ -13,7 +13,7 @@ class SamplePage extends StatefulWidget { ...@@ -13,7 +13,7 @@ class SamplePage extends StatefulWidget {
} }
class SamplePageState extends State<SamplePage> { class SamplePageState extends State<SamplePage> {
ModalRoute<Null> _route; ModalRoute<void> _route;
Future<bool> _callback() async => willPopValue; Future<bool> _callback() async => willPopValue;
...@@ -66,7 +66,7 @@ class SampleForm extends StatelessWidget { ...@@ -66,7 +66,7 @@ class SampleForm extends StatelessWidget {
// Expose the protected hasScopedWillPopCallback getter // Expose the protected hasScopedWillPopCallback getter
class TestPageRoute<T> extends MaterialPageRoute<T> { class TestPageRoute<T> extends MaterialPageRoute<T> {
TestPageRoute({ WidgetBuilder builder }) TestPageRoute({ WidgetBuilder builder })
: super(builder: builder, maintainState: true, settings: const RouteSettings()); : super(builder: builder, maintainState: true);
bool get hasCallback => super.hasScopedWillPopCallback; bool get hasCallback => super.hasScopedWillPopCallback;
} }
...@@ -84,7 +84,7 @@ void main() { ...@@ -84,7 +84,7 @@ void main() {
child: new FlatButton( child: new FlatButton(
child: const Text('X'), child: const Text('X'),
onPressed: () { onPressed: () {
showDialog<Null>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) => new SamplePage(), builder: (BuildContext context) => new SamplePage(),
); );
...@@ -138,7 +138,7 @@ void main() { ...@@ -138,7 +138,7 @@ void main() {
child: new FlatButton( child: new FlatButton(
child: const Text('X'), child: const Text('X'),
onPressed: () { onPressed: () {
Navigator.of(context).push(new MaterialPageRoute<Null>( Navigator.of(context).push(new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new SampleForm( return new SampleForm(
callback: () => new Future<bool>.value(willPopValue), callback: () => new Future<bool>.value(willPopValue),
...@@ -212,7 +212,7 @@ void main() { ...@@ -212,7 +212,7 @@ void main() {
child: new FlatButton( child: new FlatButton(
child: const Text('X'), child: const Text('X'),
onPressed: () { onPressed: () {
Navigator.of(context).push(new MaterialPageRoute<Null>( Navigator.of(context).push(new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new SampleForm( return new SampleForm(
callback: () => showYesNoAlert(context), callback: () => showYesNoAlert(context),
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
final RouteFactory generateRoute = (RouteSettings settings) => new PageRouteBuilder<Null>( final RouteFactory generateRoute = (RouteSettings settings) => new PageRouteBuilder<void>(
settings: settings, settings: settings,
pageBuilder: (BuildContext context, Animation<double> animation1, Animation<double> animation2) { pageBuilder: (BuildContext context, Animation<double> animation1, Animation<double> animation2) {
return const Placeholder(); return const Placeholder();
......
...@@ -19,7 +19,7 @@ Future<Null> pumpApp(WidgetTester tester, { GenerateAppTitle onGenerateTitle }) ...@@ -19,7 +19,7 @@ Future<Null> pumpApp(WidgetTester tester, { GenerateAppTitle onGenerateTitle })
color: kTitleColor, color: kTitleColor,
onGenerateTitle: onGenerateTitle, onGenerateTitle: onGenerateTitle,
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>( return new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return new Container(); return new Container();
} }
......
...@@ -81,7 +81,7 @@ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ ...@@ -81,7 +81,7 @@ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
}; };
class ThreeRoute extends MaterialPageRoute<Null> { class ThreeRoute extends MaterialPageRoute<void> {
ThreeRoute() : super(builder: (BuildContext context) { ThreeRoute() : super(builder: (BuildContext context) {
return new Material( return new Material(
key: routeThreeKey, key: routeThreeKey,
...@@ -96,7 +96,7 @@ class ThreeRoute extends MaterialPageRoute<Null> { ...@@ -96,7 +96,7 @@ class ThreeRoute extends MaterialPageRoute<Null> {
}); });
} }
class MutatingRoute extends MaterialPageRoute<Null> { class MutatingRoute extends MaterialPageRoute<void> {
MutatingRoute() : super(builder: (BuildContext context) { MutatingRoute() : super(builder: (BuildContext context) {
return new Hero(tag: 'a', child: const Text('MutatingRoute'), key: new UniqueKey()); return new Hero(tag: 'a', child: const Text('MutatingRoute'), key: new UniqueKey());
}); });
...@@ -363,7 +363,7 @@ void main() { ...@@ -363,7 +363,7 @@ void main() {
testWidgets('Popping on first frame does not cause hero observer to crash', (WidgetTester tester) async { testWidgets('Popping on first frame does not cause hero observer to crash', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp( await tester.pumpWidget(new MaterialApp(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => new Hero(tag: 'test', child: new Container()), builder: (BuildContext context) => new Hero(tag: 'test', child: new Container()),
); );
...@@ -389,7 +389,7 @@ void main() { ...@@ -389,7 +389,7 @@ void main() {
testWidgets('Overlapping starting and ending a hero transition works ok', (WidgetTester tester) async { testWidgets('Overlapping starting and ending a hero transition works ok', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp( await tester.pumpWidget(new MaterialApp(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => new Hero(tag: 'test', child: new Container()), builder: (BuildContext context) => new Hero(tag: 'test', child: new Container()),
); );
...@@ -432,7 +432,7 @@ void main() { ...@@ -432,7 +432,7 @@ void main() {
return new FlatButton( return new FlatButton(
child: const Text('push'), child: const Text('push'),
onPressed: () { onPressed: () {
Navigator.push(context, new PageRouteBuilder<Null>( Navigator.push(context, new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) { pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
return const Text('fail'); return const Text('fail');
}, },
...@@ -569,9 +569,9 @@ void main() { ...@@ -569,9 +569,9 @@ void main() {
// After flying in the opposite direction for 50ms Hero 'a' will // After flying in the opposite direction for 50ms Hero 'a' will
// be smaller than it was, but bigger than its initial size. // be smaller than it was, but bigger than its initial size.
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
final double height100ms = tester.getSize(find.byKey(firstKey)).height; final double height200ms = tester.getSize(find.byKey(firstKey)).height;
expect(height100ms, greaterThan(height150ms)); expect(height200ms, greaterThan(height150ms));
expect(finalHeight, lessThan(height100ms)); expect(finalHeight, lessThan(height200ms));
// Hero a's return flight at 149ms. The outgoing (push) flight took // Hero a's return flight at 149ms. The outgoing (push) flight took
// 150ms so we should be just about back to where Hero 'a' started. // 150ms so we should be just about back to where Hero 'a' started.
...@@ -593,7 +593,7 @@ void main() { ...@@ -593,7 +593,7 @@ void main() {
StateSetter heroCardSetState; StateSetter heroCardSetState;
// Show a 200x200 Hero tagged 'H', with key routeHeroKey // Show a 200x200 Hero tagged 'H', with key routeHeroKey
final MaterialPageRoute<Null> route = new MaterialPageRoute<Null>( final MaterialPageRoute<void> route = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
...@@ -695,7 +695,7 @@ void main() { ...@@ -695,7 +695,7 @@ void main() {
const Key routeContainerKey = const Key('route hero container'); const Key routeContainerKey = const Key('route hero container');
// Show a 200x200 Hero tagged 'H', with key routeHeroKey // Show a 200x200 Hero tagged 'H', with key routeHeroKey
final MaterialPageRoute<Null> route = new MaterialPageRoute<Null>( final MaterialPageRoute<void> route = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
...@@ -777,7 +777,7 @@ void main() { ...@@ -777,7 +777,7 @@ void main() {
const Key routeContainerKey = const Key('route hero container'); const Key routeContainerKey = const Key('route hero container');
// Show a 200x200 Hero tagged 'H', with key routeHeroKey // Show a 200x200 Hero tagged 'H', with key routeHeroKey
final MaterialPageRoute<Null> route = new MaterialPageRoute<Null>( final MaterialPageRoute<void> route = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
...@@ -855,7 +855,7 @@ void main() { ...@@ -855,7 +855,7 @@ void main() {
const Key heroBCKey = const Key('BC hero'); const Key heroBCKey = const Key('BC hero');
// Show a 150x150 Hero tagged 'BC' // Show a 150x150 Hero tagged 'BC'
final MaterialPageRoute<Null> routeC = new MaterialPageRoute<Null>( final MaterialPageRoute<void> routeC = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
...@@ -872,7 +872,7 @@ void main() { ...@@ -872,7 +872,7 @@ void main() {
); );
// Show a height=200 Hero tagged 'AB' and a height=50 Hero tagged 'BC' // Show a height=200 Hero tagged 'AB' and a height=50 Hero tagged 'BC'
final MaterialPageRoute<Null> routeB = new MaterialPageRoute<Null>( final MaterialPageRoute<void> routeB = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
...@@ -956,7 +956,7 @@ void main() { ...@@ -956,7 +956,7 @@ void main() {
}); });
testWidgets('Stateful hero child state survives flight', (WidgetTester tester) async { testWidgets('Stateful hero child state survives flight', (WidgetTester tester) async {
final MaterialPageRoute<Null> route = new MaterialPageRoute<Null>( final MaterialPageRoute<void> route = new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new Material( return new Material(
child: new ListView( child: new ListView(
......
...@@ -91,6 +91,7 @@ class TestObserver extends NavigatorObserver { ...@@ -91,6 +91,7 @@ class TestObserver extends NavigatorObserver {
OnObservation onPushed; OnObservation onPushed;
OnObservation onPopped; OnObservation onPopped;
OnObservation onRemoved; OnObservation onRemoved;
OnObservation onReplaced;
@override @override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
...@@ -111,6 +112,12 @@ class TestObserver extends NavigatorObserver { ...@@ -111,6 +112,12 @@ class TestObserver extends NavigatorObserver {
if (onRemoved != null) if (onRemoved != null)
onRemoved(route, previousRoute); onRemoved(route, previousRoute);
} }
@override
void didReplace({ Route<dynamic> oldRoute, Route<dynamic> newRoute }) {
if (onReplaced != null)
onReplaced(newRoute, oldRoute);
}
} }
void main() { void main() {
...@@ -193,19 +200,19 @@ void main() { ...@@ -193,19 +200,19 @@ void main() {
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
if (settings.isInitialRoute) { if (settings.isInitialRoute) {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
child: const Text('Next'), child: const Text('Next'),
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
new MaterialPageRoute<Null>( new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new RaisedButton( return new RaisedButton(
child: const Text('Inner page'), child: const Text('Inner page'),
onPressed: () { onPressed: () {
Navigator.of(context, rootNavigator: true).push( Navigator.of(context, rootNavigator: true).push(
new MaterialPageRoute<Null>( new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return const Text('Dialog'); return const Text('Dialog');
} }
...@@ -608,7 +615,7 @@ void main() { ...@@ -608,7 +615,7 @@ void main() {
testWidgets('remove a route whose value is awaited', (WidgetTester tester) async { testWidgets('remove a route whose value is awaited', (WidgetTester tester) async {
Future<String> pageValue; Future<String> pageValue;
final Map<String, WidgetBuilder> pageBuilders = <String, WidgetBuilder>{ final Map<String, WidgetBuilder> pageBuilders = <String, WidgetBuilder>{
'/': (BuildContext context) => new OnTapPage(id: '/', onTap: () { pageValue = Navigator.pushNamed(context, '/A'); }), '/': (BuildContext context) => new OnTapPage(id: '/', onTap: () { pageValue = Navigator.pushNamed(context, '/A'); }),
'/A': (BuildContext context) => new OnTapPage(id: 'A', onTap: () { Navigator.pop(context, 'A'); }), '/A': (BuildContext context) => new OnTapPage(id: 'A', onTap: () { Navigator.pop(context, 'A'); }),
}; };
final Map<String, Route<String>> routes = <String, Route<String>>{}; final Map<String, Route<String>> routes = <String, Route<String>>{};
...@@ -633,5 +640,133 @@ void main() { ...@@ -633,5 +640,133 @@ void main() {
navigator.removeRoute(routes['/A']); // stack becomes /, pageValue will not complete navigator.removeRoute(routes['/A']); // stack becomes /, pageValue will not complete
}); });
testWidgets('replacing route can be observed', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key = new GlobalKey<NavigatorState>();
final List<String> log = <String>[];
final TestObserver observer = new TestObserver()
..onPushed = (Route<dynamic> route, Route<dynamic> previousRoute) {
log.add('pushed ${route.settings.name} (previous is ${previousRoute == null ? "<none>" : previousRoute.settings.name})');
}
..onPopped = (Route<dynamic> route, Route<dynamic> previousRoute) {
log.add('popped ${route.settings.name} (previous is ${previousRoute == null ? "<none>" : previousRoute.settings.name})');
}
..onRemoved = (Route<dynamic> route, Route<dynamic> previousRoute) {
log.add('removed ${route.settings.name} (previous is ${previousRoute == null ? "<none>" : previousRoute.settings.name})');
}
..onReplaced = (Route<dynamic> newRoute, Route<dynamic> oldRoute) {
log.add('replaced ${oldRoute.settings.name} with ${newRoute.settings.name}');
};
Route<void> routeB;
await tester.pumpWidget(new MaterialApp(
navigatorKey: key,
navigatorObservers: <NavigatorObserver>[observer],
home: new FlatButton(
child: const Text('A'),
onPressed: () {
key.currentState.push<void>(routeB = new MaterialPageRoute<void>(
settings: const RouteSettings(name: 'B'),
builder: (BuildContext context) {
return new FlatButton(
child: const Text('B'),
onPressed: () {
key.currentState.push<void>(new MaterialPageRoute<int>(
settings: const RouteSettings(name: 'C'),
builder: (BuildContext context) {
return new FlatButton(
child: const Text('C'),
onPressed: () {
key.currentState.replace(
oldRoute: routeB,
newRoute: new MaterialPageRoute<int>(
settings: const RouteSettings(name: 'D'),
builder: (BuildContext context) {
return const Text('D');
},
),
);
},
);
},
));
},
);
},
));
},
),
));
expect(log, <String>['pushed / (previous is <none>)']);
await tester.tap(find.text('A'));
await tester.pump();
await tester.pump(const Duration(seconds: 1));
expect(log, <String>['pushed / (previous is <none>)', 'pushed B (previous is /)']);
await tester.tap(find.text('B'));
await tester.pump();
await tester.pump(const Duration(seconds: 1));
expect(log, <String>['pushed / (previous is <none>)', 'pushed B (previous is /)', 'pushed C (previous is B)']);
await tester.tap(find.text('C'));
await tester.pump();
await tester.pump(const Duration(seconds: 1));
expect(log, <String>['pushed / (previous is <none>)', 'pushed B (previous is /)', 'pushed C (previous is B)', 'replaced B with D']);
});
testWidgets('ModalRoute.of sets up a route to rebuild if its state changes', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key = new GlobalKey<NavigatorState>();
final List<String> log = <String>[];
Route<void> routeB;
await tester.pumpWidget(new MaterialApp(
navigatorKey: key,
home: new FlatButton(
child: const Text('A'),
onPressed: () {
key.currentState.push<void>(routeB = new MaterialPageRoute<void>(
settings: const RouteSettings(name: 'B'),
builder: (BuildContext context) {
log.add('building B');
return new FlatButton(
child: const Text('B'),
onPressed: () {
key.currentState.push<void>(new MaterialPageRoute<int>(
settings: const RouteSettings(name: 'C'),
builder: (BuildContext context) {
log.add('building C');
log.add('found ${ModalRoute.of(context).settings.name}');
return new FlatButton(
child: const Text('C'),
onPressed: () {
key.currentState.replace(
oldRoute: routeB,
newRoute: new MaterialPageRoute<int>(
settings: const RouteSettings(name: 'D'),
builder: (BuildContext context) {
log.add('building D');
return const Text('D');
},
),
);
},
);
},
));
},
);
},
));
},
),
));
expect(log, <String>[]);
await tester.tap(find.text('A'));
await tester.pumpAndSettle(const Duration(milliseconds: 10));
expect(log, <String>['building B']);
await tester.tap(find.text('B'));
await tester.pumpAndSettle(const Duration(milliseconds: 10));
expect(log, <String>['building B', 'building C', 'found C']);
await tester.tap(find.text('C'));
await tester.pumpAndSettle(const Duration(milliseconds: 10));
expect(log, <String>['building B', 'building C', 'found C', 'building D']);
key.currentState.pop<void>();
await tester.pumpAndSettle(const Duration(milliseconds: 10));
expect(log, <String>['building B', 'building C', 'found C', 'building D', 'building C', 'found C']);
});
} }
...@@ -86,7 +86,7 @@ void main() { ...@@ -86,7 +86,7 @@ void main() {
child: new Builder( child: new Builder(
key: insideKey, key: insideKey,
builder: (BuildContext context) { builder: (BuildContext context) {
final PageRoute<Null> route = ModalRoute.of(context); final PageRoute<void> route = ModalRoute.of(context);
return new Column( return new Column(
children: <Widget>[ children: <Widget>[
new TestTransition( new TestTransition(
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class TestOverlayRoute extends OverlayRoute<Null> { class TestOverlayRoute extends OverlayRoute<void> {
TestOverlayRoute({ RouteSettings settings }) : super(settings: settings);
@override @override
Iterable<OverlayEntry> createOverlayEntries() sync* { Iterable<OverlayEntry> createOverlayEntries() sync* {
yield new OverlayEntry(builder: _build); yield new OverlayEntry(builder: _build);
...@@ -311,7 +312,7 @@ void main() { ...@@ -311,7 +312,7 @@ void main() {
await tester.pumpWidget(new MaterialApp(routes: routes)); await tester.pumpWidget(new MaterialApp(routes: routes));
final PageRoute<Null> route = new MaterialPageRoute<Null>( final PageRoute<void> route = new MaterialPageRoute<void>(
settings: const RouteSettings(name: '/page'), settings: const RouteSettings(name: '/page'),
builder: (BuildContext context) => const Center(child: const Text('page')), builder: (BuildContext context) => const Center(child: const Text('page')),
); );
......
...@@ -37,13 +37,13 @@ Future<Null> performTest(WidgetTester tester, bool maintainState) async { ...@@ -37,13 +37,13 @@ Future<Null> performTest(WidgetTester tester, bool maintainState) async {
key: navigatorKey, key: navigatorKey,
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/') { if (settings.name == '/') {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (_) => new Container(child: const ThePositiveNumbers(from: 0)), builder: (_) => new Container(child: const ThePositiveNumbers(from: 0)),
maintainState: maintainState, maintainState: maintainState,
); );
} else if (settings.name == '/second') { } else if (settings.name == '/second') {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
settings: settings, settings: settings,
builder: (_) => new Container(child: const ThePositiveNumbers(from: 10000)), builder: (_) => new Container(child: const ThePositiveNumbers(from: 10000)),
maintainState: maintainState, maintainState: maintainState,
......
...@@ -45,9 +45,11 @@ class TestRoute extends LocalHistoryRoute<String> { ...@@ -45,9 +45,11 @@ class TestRoute extends LocalHistoryRoute<String> {
} }
@override @override
void didReplace(covariant TestRoute oldRoute) { void didReplace(Route<dynamic> oldRoute) {
log('didReplace ${oldRoute.name}'); expect(oldRoute, const isInstanceOf<TestRoute>());
super.didReplace(oldRoute); final TestRoute castRoute = oldRoute;
log('didReplace ${castRoute.name}');
super.didReplace(castRoute);
} }
@override @override
...@@ -60,15 +62,19 @@ class TestRoute extends LocalHistoryRoute<String> { ...@@ -60,15 +62,19 @@ class TestRoute extends LocalHistoryRoute<String> {
} }
@override @override
void didPopNext(covariant TestRoute nextRoute) { void didPopNext(Route<dynamic> nextRoute) {
log('didPopNext ${nextRoute.name}'); expect(nextRoute, const isInstanceOf<TestRoute>());
super.didPopNext(nextRoute); final TestRoute castRoute = nextRoute;
log('didPopNext ${castRoute.name}');
super.didPopNext(castRoute);
} }
@override @override
void didChangeNext(covariant TestRoute nextRoute) { void didChangeNext(Route<dynamic> nextRoute) {
log('didChangeNext ${nextRoute?.name}'); expect(nextRoute, anyOf(isNull, const isInstanceOf<TestRoute>()));
super.didChangeNext(nextRoute); final TestRoute castRoute = nextRoute;
log('didChangeNext ${castRoute?.name}');
super.didChangeNext(castRoute);
} }
@override @override
......
...@@ -54,7 +54,7 @@ Widget buildFrame({ ...@@ -54,7 +54,7 @@ Widget buildFrame({
localizationsDelegates: delegates, localizationsDelegates: delegates,
localeResolutionCallback: localeResolutionCallback, localeResolutionCallback: localeResolutionCallback,
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<Null>( return new MaterialPageRoute<void>(
builder: (BuildContext context) { builder: (BuildContext context) {
return buildContent(context); return buildContent(context);
} }
......
...@@ -145,7 +145,7 @@ void main() { ...@@ -145,7 +145,7 @@ void main() {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Navigator( child: new Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<dynamic>(builder: (BuildContext context) { return new MaterialPageRoute<void>(builder: (BuildContext context) {
return new FlatButton( return new FlatButton(
onPressed: () { onPressed: () {
showTimePicker(context: context, initialTime: const TimeOfDay(hour: 7, minute: 0)); showTimePicker(context: context, initialTime: const TimeOfDay(hour: 7, minute: 0));
......
...@@ -153,7 +153,7 @@ Widget buildFrame({ ...@@ -153,7 +153,7 @@ Widget buildFrame({
localeResolutionCallback: localeResolutionCallback, localeResolutionCallback: localeResolutionCallback,
supportedLocales: supportedLocales, supportedLocales: supportedLocales,
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return new PageRouteBuilder<Null>( return new PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) { pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
return buildContent(context); return buildContent(context);
} }
......
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