Flutter – Saving and Restoring with SharedPreferences

In this article we will explore the basics of saving data locally in Flutter. There are a few different approaches you can take to get this done but we'll be exploring the most simplest one by using the shared preferences plugin. You'll find this to be a good approach unless the data you need to save begins to grow to more than say a few dozen items. In that case you may want to explore saving to a SQLite database.

Creating a Flutter app

For the purposes of demonstrating how to save data locally, we will create a Flutter app that contains a single user settings page. The app will present the settings page to the user and immediately persist any changes the user makes to the settings. Here is what our app will look like when finished:

Sample App

Our application will contain a total of five settings we need to save. Here is the code for declarings the five settings:

  //Email address
  String _email;
  //Whether or not the app can send out notifications
  bool _notifications = true;
  //Whether or not pin codes can be used to authenticate
  bool _allowPinCodes = false;
  //Whether or not the presence of white-listed phones can be used to authenticate
  bool _allowPhonePresenceDetection = false;
  //Preferred temperature unit - fahrenheit or celsius?
  String _temperatureUnit = 'fahrenheit';

Adding the Shared Preferences Package

In order to save our settings, we need to bring in the shared preferences package. To do so, open up the pubspec.yaml file and add the package reference directly below the flutter sdk as follows:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^0.5.3

Save the file and if you have VS Code and the Flutter extension setup like I recommend here, you will see the following output and the package is downloaded and ready for you to use.

[save_local] flutter packages get
Running "flutter packages get" in save_local...                     2.2s
exit code 0

You may also do this manually by jumping out to a terminal window and executing the following command:

flutter pub get

For more information on using packages in your Flutter apps, click here.

Introduction to the SharedPreferences Plugin

Both the saving and restoring of data is handled through the SharedPreferences class. Data is stored and retrieved using a key-value approach with a Map<String, Object> under the hood. But all you have to consider is you both get and set a value using a key.

In order to use SharedPreferences, you need to obtain a reference to it by calling the getInstance method. This method is asynchronous and returns a Future\<SharedPreferences> instance. Therefore it is important to await the getInstance() method. I've blogged about async and await in Dart and Flutter before in case you are interested. Here is the code to get a reference to SharedPreferences:

final sharedPrefs = await SharedPreferences.getInstance();

Saving Data using SharedPreferences

The SharedPreferences class has several set methods to give you a way to store data. You call the appropriate set method based on the type you want to save.

  • setBool
  • setDouble
  • setInt
  • setString
  • setStringList

But as you can see, there is no way direct way to save an object - for that I would suggest alternative approaches such as using internal storage or SQLite. What we will do in this demo is call the appropriate SharedPreferences set method based on what type of data we receive. This keeps our code that saves data all in one place:

  save(String key, dynamic value) async {
    final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
    if (value is bool) {
      sharedPrefs.setBool(key, value);
    } else if (value is String) {
      sharedPrefs.setString(key, value);
    } else if (value is int) {
      sharedPrefs.setInt(key, value);
    } else if (value is double) {
      sharedPrefs.setDouble(key, value);
    } else if (value is List<String>) {
      sharedPrefs.setStringList(key, value);
    }
  }

This save method makes it easy to save a setting. For example if we have a SwitchListTile that we wish to save the on/off value for, we need only provide an onChanged handler and call the save method:

  new SwitchListTile(
    title: const Text('Notifications'),
    value: _notifications,
    onChanged: (bool value) {
      setState(() {
        _notifications = value;        
      });
      save('notifications', value);
    },
    secondary: const Icon(Icons.notifications),
  ),

You may wonder about the call to setState(). This really has nothing to do with the save but all to do with the fact that the SwitchListTile is watching _notifications as its value and in order for the UI to recognize the value of _notifications changing, setState is required. Read more about setState within the Flutter docs.

Restoring Data using SharedPreferences

The SharedPreferences class has several get methods that are counterparts to its set methods. As you might expect there is a get method for each supported type:

  • getBool
  • getDouble
  • getInt
  • getString
  • getStringList
  • get

In addition to the get methods, several utility methods are present

  • getKeys - Returns all keys in the persistent storage
  • clear - Removes all data from the persistent storage
  • containsKey - Returns true if persistent storage the contains the given key
  • reload - Fetches the latest values from the host platform (useful if changes outside your code are known to have been made)
  • remove - Removes an entry from persistent storage
  • commit - deprecated, do not use.

With the knowledge of how the API for SharedPreferences works, lets put together our game plan for restoring data. We'll want to do this whenever the application is started up. Fortunately for us Flutter's stateful widgets have just the method we need to override to serve our needs - initState. We can override initState and use the SharedPreferences class to restore any settings for our widget before the widget is displayed.

  @override
  void initState() {
    super.initState();
    restore();
  }

  restore() async {
    final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
    setState(() {
      _notifications = (sharedPrefs.getBool('notifications') ?? false);
      //TODO: More restoring of settings would go here...
    });
  }  

Now, if we were to run our app we would see the settings restored to the way we left them the last time we ran the application!

That's a Wrap!

Using SharedPreferences is a really easy way to save and restore simple settings for your app. The API may not seem all that robust but it gets the job done. Just remember the basics here are:

  • When a setting is changed call the appropriate save method passing in the key and value for your setting.
  • Use your widget's initState method to restore all settings before your widget is displayed by calling the appropriate get method and key.
  • SharedPreferences is a good choice for storing smaller quantities of simple types.

Leave a Reply

Your email address will not be published. Required fields are marked *