I have a page that pushes another page and waits for the returned/popped value to process. I'd like this second page to be able to delegate if possible (let another page return the value). Something like this:
// page 1
Navigator.of(context).push(Page2()).then((value) => print(value)); // process value; perhaps setState or whatever
// page 2
Navigator.of(context).pushReplacement(Page3()); // let another page handle the rest
// page 3
Navigator.of(context).pop(99);
However, the future on the first page never returns and the value is never printed (or processed in whichever way I see fit). The reason for the pushReplacement is I don't want the user to go back to page 2 if they've made it to the third page.
Here's a sample flutter app you can try on https://dartpad.dartlang.org/flutter to see what I mean.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Page1(),
);
}
}
class Page1 extends StatefulWidget {
@override
Page1State createState() => Page1State();
}
class Page1State extends State<Page1> {
List<int> numbers = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text('Page 1'),
...numbers.map((number) => Text(number.toString())),
RaisedButton(
child: Text('go to page 2'),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => Page2()))
.then((number) {
if (number != null) {
setState(() {
numbers.add(number);
});
}
});
},
),
],
),
),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text('Ready?'),
RaisedButton(
child: Text('Yes'),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => Page3()));
},
),
RaisedButton(
child: Text('No'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
);
}
}
class Page3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
Text('Pick a number'),
...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(
(number) => RaisedButton(
child: Text(number.toString()),
onPressed: () => Navigator.of(context).pop(number),
),
),
RaisedButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
);
}
}
I must clarify the use case. The first page will fetch data from a server or whatever, so I'd use a FutureBuilder or similar. The second page is a form to create/add additional items. The form is submitted and if the server is happy with the data, the response will contain the newly created data. I then want to replace the current form page with a success page showing the data. When the user pops this page, I want the first page's list to be updated with the data.
Fancy state management like Bloc, ValueNotifier, or similar could be used but this page is short lived and I'd like to implement this feature with as little boilerplate code as possible. Also, I have found that using these state management classes require being added above/before the MaterialApp if other pages need access. For a page which might be buried deep in my app, I'd like to avoid adding a Bloc/ValueNotifier/whatever in main. That just feels like giving it too much importance.