How to pass data between screens in Flutter

In this article we will talk about three methods by which data can be passed from one screen to another in flutter.

1. Using constructors

This is a very well known technique that is used in other languages as well. What we do is we pass the needed data in the constructor when we instatiate the target class.

Lets assume that we have a screen say ConstructorScreen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ConstructorScreen extends StatelessWidget {
String message;

  ConstructorScreen(String m){
    this.message = m;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Screen with constructor data"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[Text("Data received"), Text(message)],
        ),
      ),
    );
  }
}
In here, we are displaying the message that is passed from another screen. To do this, when we instantiate the above class we will set the message in the constructor.Like so:
1
2
3
4
5
6
7
8
9
. . .
. . . 
 Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => 
        ConstructorScreen("Hello from main to constructor screen")),
    );
. . .
. . .

2. Using arguments in navigator

The pushNamed method of Nagigator can be used for passing arguments. Complex objects and primitive data types can be passed. The snippet below shows how to pass a string.

1
2
3
4
5
Navigator.pushNamed(
    context,
    '/nav',
    arguments: "Hello from main to Navigation screen",
);
And this argument can be used in the new screen being opened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
. . .
. . .
final String _message = ModalRoute.of(context).settings.arguments;
    return Scaffold(
      appBar: AppBar(
        title: Text("Screen with navigation data"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[Text("Data received"), 
            Text(_message)],
        ),
      ),
    );
. . .
. . .

3. Using shared preferences

The last method is by using SharedPreferences. This method is not recommended but has been included for completion.

If you have a relatively small collection of key-values that you’d like to save, you should use the SharedPreferences APIs. A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared.

We use shared_preferences package from flutter to store our message and retrieve in our target screen.

1
2
3
4
5
6
7
8
9
. . .
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("message", "Hello from main to Shared Pref screen");

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SharedPrefScreen()),
);
. . .
Notice that we have used await here, it is because getting an instance is a async process. The code should be included in an async function.

From the target screen, we can read it in the following way:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
. . .
. . .
String _message;
. . .
. . .
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
    _message = (prefs.getString('message') ?? "No data received");
});
. . .
. . .

The full code is available at github