Passing data between screens in Flutter
This answer will cover both passing data forward and passing data back. Unlike Android Activities and iOS ViewControllers, different screens in Flutter are just widgets. Navigating between them involves creating something called a route and using the Navigator
to push and pop the routes on and off the stack.
Passing data forward to the next screen
To send data to the next screen you do the following things:
Make the
SecondScreen
constructor take a parameter for the type of data that you want to send to it. In this particular example, the data is defined to be aString
value and is set here withthis.text
.class SecondScreen extends StatelessWidget { final String text; SecondScreen({Key key, @required this.text}) : super(key: key); ...
Then use the
Navigator
in theFirstScreen
widget to push a route to theSecondScreen
widget. You put the data that you want to send as a parameter in its constructor.Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(text: 'Hello',), ));
The full code for main.dart
is here:
import 'package:flutter/material.dart';void main() { runApp(MaterialApp( title: 'Flutter', home: FirstScreen(), ));}class FirstScreen extends StatefulWidget { @override _FirstScreenState createState() { return _FirstScreenState(); }}class _FirstScreenState extends State<FirstScreen> { // this allows us to access the TextField text TextEditingController textFieldController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('First screen')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(32.0), child: TextField( controller: textFieldController, style: TextStyle( fontSize: 24, color: Colors.black, ), ), ), RaisedButton( child: Text( 'Go to second screen', style: TextStyle(fontSize: 24), ), onPressed: () { _sendDataToSecondScreen(context); }, ) ], ), ); } // get the text in the TextField and start the Second Screen void _sendDataToSecondScreen(BuildContext context) { String textToSend = textFieldController.text; Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(text: textToSend,), )); }}class SecondScreen extends StatelessWidget { final String text; // receive data from the FirstScreen as a parameter SecondScreen({Key key, @required this.text}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Second screen')), body: Center( child: Text( text, style: TextStyle(fontSize: 24), ), ), ); }}
Passing data back to the previous screen
When passing data back you need to do the following things:
In the
FirstScreen
, use theNavigator
to push (start) theSecondScreen
in anasync
method and wait for the result that it will return when it finishes.final result = await Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(), ));
In the
SecondScreen
, include the data that you want to pass back as a parameter when you pop theNavigator
.Navigator.pop(context, 'Hello');
Then in the
FirstScreen
theawait
will finish and you can use the result.setState(() { text = result;});
Here is the complete code for main.dart
for your reference.
import 'package:flutter/material.dart';void main() { runApp(MaterialApp( title: 'Flutter', home: FirstScreen(), ));}class FirstScreen extends StatefulWidget { @override _FirstScreenState createState() { return _FirstScreenState(); }}class _FirstScreenState extends State<FirstScreen> { String text = 'Text'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('First screen')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(32.0), child: Text( text, style: TextStyle(fontSize: 24), ), ), RaisedButton( child: Text( 'Go to second screen', style: TextStyle(fontSize: 24), ), onPressed: () { _awaitReturnValueFromSecondScreen(context); }, ) ], ), ), ); } void _awaitReturnValueFromSecondScreen(BuildContext context) async { // start the SecondScreen and wait for it to finish with a result final result = await Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(), )); // after the SecondScreen result comes back update the Text widget with it setState(() { text = result; }); }}class SecondScreen extends StatefulWidget { @override _SecondScreenState createState() { return _SecondScreenState(); }}class _SecondScreenState extends State<SecondScreen> { // this allows us to access the TextField text TextEditingController textFieldController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Second screen')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(32.0), child: TextField( controller: textFieldController, style: TextStyle( fontSize: 24, color: Colors.black, ), ), ), RaisedButton( child: Text( 'Send text back', style: TextStyle(fontSize: 24), ), onPressed: () { _sendDataBack(context); }, ) ], ), ); } // get the text in the TextField and send it back to the FirstScreen void _sendDataBack(BuildContext context) { String textToSendBack = textFieldController.text; Navigator.pop(context, textToSendBack); }}
Get Perfect Solution :
From 1st Screen navigate to others as:
Navigator.pushNamed(context, "second",arguments: {"name" : "Bijendra", "rollNo": 65210});},
On Second Screen in build method get as :
@overrideWidget build(BuildContext context) { final Map<String, Object>rcvdData = ModalRoute.of(context).settings.arguments; print("rcvd fdata ${rcvdData['name']}"); print("rcvd fdata ${rcvdData}"); return Scaffold(appBar: AppBar(title: Text("Second")), body: Container(child: Column(children: <Widget>[ Text("Second"), ],),),);}
This solution is very easy by passing variables in constructor:
first page:
Navigator.of(context).push(MaterialPageRoute(builder:(context)=>SecondPage('something')));
second page:
class SecondPage extends StatefulWidget { String something; SecondPage(this.something); @override State<StatefulWidget> createState() { return SecondPageState(this.something); }}class SecondPageState extends State<SecondPage> { String something; SecondPageState(this.something); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( //now you have passing variable title: Text(something), ), ... }