问题
When pushing two routes at the same time to the Navigator and using RouteAware to get updated about the current state, the didPopNext() of the first route is not called.
It seems that RouteObserver.didPush() (which would call didPushNext) is called for both routes before the didChangeDependencies() of FirstWiget is called where I subscribe to the routeObserver.
This is what I expect and what I get, when pushing the routes one after the other and waiting for the widget to appear:
I/flutter (30927): Navigator.push(FirstWidget)
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didPush FirstWidget
I/flutter (30927): build FirstWidget
I/flutter (30927): Navigator.push(SecondWidget)
I/flutter (30927): didPushNext FirstWidget
I/flutter (30927): didChangeDependencies SecondWidget
I/flutter (30927): didPush SecondWidget
I/flutter (30927): build SecondWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): build FirstWidget
When pushing both at the same time:
I/flutter (30927): Navigator.push(FirstWidget)
I/flutter (30927): Navigator.push(SecondWidget)
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didPush FirstWidget
I/flutter (30927): build FirstWidget
I/flutter (30927): didChangeDependencies SecondWidget
I/flutter (30927): didPush SecondWidget
I/flutter (30927): build SecondWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): build FirstWidget
This is the running example:
import 'package:flutter/material.dart';
RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
void main() {
runApp(MaterialApp(
title: 'Navigation Test',
home: StartWidget(),
navigatorObservers: <NavigatorObserver>[routeObserver],
));
}
class StartWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Start'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('Open both routes'),
onPressed: () {
print("Navigator.push(FirstWidget)");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FirstWidget()),
);
print("Navigator.push(SecondWidget)");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondWidget()),
);
},
),
RaisedButton(
child: Text('Open FirstWidget'),
onPressed: () {
print("Navigator.push(FirstWidget)");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FirstWidget()),
);
},
),
],
),
),
);
}
}
class FirstWidget extends StatefulWidget {
@override
_FirstWidgetState createState() => _FirstWidgetState();
}
class _FirstWidgetState extends RouteAwareState<FirstWidget> {
Widget build(BuildContext context) {
print("build $widget");
return Scaffold(
appBar: AppBar(
title: Text('FirstWidget'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('Open SecondWidget'),
onPressed: () {
print("Navigator.push(SecondWidget)");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondWidget()),
);
},
),
RaisedButton(
child: Text('back'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}
class SecondWidget extends StatefulWidget {
@override
_SecondWidgetState createState() => _SecondWidgetState();
}
class _SecondWidgetState extends RouteAwareState<SecondWidget> {
@override
Widget build(BuildContext context) {
print("build $widget");
return Scaffold(
appBar: AppBar(
title: Text('SecondWidget'),
),
body: Center(
child: RaisedButton(
child: Text('back'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
abstract class RouteAwareState<T extends StatefulWidget> extends State<T>
with RouteAware {
@override
void didChangeDependencies() {
print("didChangeDependencies $widget");
routeObserver.subscribe(this, ModalRoute.of(context)); //Subscribe it here
super.didChangeDependencies();
}
@override
void didPush() {
print('didPush $widget');
}
@override
void didPopNext() {
print('didPopNext $widget');
}
@override
void didPop() {
print('didPop $widget');
}
@override
void didPushNext() {
print('didPushNext $widget');
}
@override
void dispose() {
print("dispose $widget");
routeObserver.unsubscribe(this);
super.dispose();
}
}
Note: Edited to include the code directly.
回答1:
When placing
WidgetsBinding.instance.addPostFrameCallback()
between the two Navigator.push()
calls, the FirstWidget is registered correctly and the didPushNext FirstWidget
callback is triggered.
See flutter issue #55949 for more details.
来源:https://stackoverflow.com/questions/61409296/routeaware-didpushnext-is-not-called-when-pushing-two-routes-at-once