Yes, Flutter makes this pattern easy using Navigator.push
and Navigator.pop
.
Here’s a full working example:
Screen A (caller):
import 'package:flutter/material.dart';
import 'screen_b.dart'; // assume you created this separately
class ScreenA extends StatefulWidget {
@override
_ScreenAState createState() => _ScreenAState();
}
class _ScreenAState extends State<ScreenA> {
String returnedData = 'No data yet';
void _navigateAndGetData() async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => ScreenB()),
);
if (result != null) {
setState(() {
returnedData = result;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Screen A")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Returned data: $returnedData'),
ElevatedButton(
onPressed: _navigateAndGetData,
child: Text('Go to Screen B'),
),
],
),
),
);
}
}
Screen B (Returns Data) :
import 'package:flutter/material.dart';
class ScreenB extends StatelessWidget {
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Screen B")),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(controller: _controller),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pop(context, _controller.text); // return data
},
child: Text('Send back data'),
),
],
),
),
);
}
}
Navigator.push
returns a Future
that completes when the pushed route is popped.
In ScreenB
, Navigator.pop(context, data)
returns the data to the previous screen.
You can await
the result and use setState
to update the UI.
This is the Flutter-recommended way to pass data back when popping a route.
Navigator.push
returns a Future?In Flutter, Navigator.push()
creates a new route (i.e., a screen or a page) and adds it to the navigation stack. This is an asynchronous operation — the new screen stays on top until it's popped.
Because of this, Navigator.push()
returns a Future<T>
, where T
is the data type you expect when the screen is popped. The await
keyword lets you wait for this result without blocking the UI.
final result = await Navigator.push(...); // result gets assigned when the screen pops
Navigator.pop(context, data)
work?When you call:
Navigator.pop(context, 'some data');
You're removing the current screen from the navigation stack and sending data back to the screen below. That data becomes the result that was awaited by Navigator.push
.
Think of it like a dialog that returns a value when closed — except you're navigating entire screens.
This navigation-and-return-data pattern is especially useful in cases like:
Picking a value from a list (e.g., selecting a city or a contact).
Filling out a form and submitting it.
Performing any interaction in a secondary screen that should inform the calling screen of the result.