Flutter Package Preview: shared_preferences
Tags: flutter, dart, tutorial, mobile
Published: 2021-06-12 15:15:00

Welcome to my new series of helpful preview articles, "Flutter Package Preview" where I talk about different packages on pub.dev and how to use them!

For the first entry in this series, I'm excited to introduce [shared_preferences!] (https://pub.dev/packages/shared_preferences)

I always recommend reading through the pub.dev page of any new package before using it, so here's where you can find [shared_preferences.] (https://pub.dev/packages/shared_preferences)

## What is shared_preferences

shared_preferences is a package that helps streamline storing persistent data in a users, you guessed it, Shared Preferences! Each device type stores simple data in different ways. On iOS and macOS devices, this simple data is stored in what they call NSUserDefaults. On Android and other platforms, it's stored in what they call SharedPreferences. 

This data can be any of the following data types: int, bool, double, String, or List<String>. It also persists between device or app restarts! So your user doesn't have to configure the app every time they open it!

## How to include shared_preferences in your project

So you want to use this package in your project?! Awesome! Either run `flutter pub add shared_preferences` in your terminal or simply add this statement to your pubspec.yaml file.
```
dependencies:
  shared_preferences: ^2.0.6
```

## How to use it in practice

First, you'll need to include the import statement at the top of whichever class you'd like to use it in.
`import 'package:shared_preferences/shared_preferences.dart';`

Great! Now before you can save or fetch any data from the persistent storage you need to get an instance of the SharedPreferences object.

```
    SharedPreferences prefs = await SharedPreferences.getInstance();
```

You'll notice that this uses the `await` keyword. This means that getting an instance of SharedPreferences is asynchronous and requires a little extra setup. You'll either need to use a FutureBuilder widget, or simply wrap it in an asynchronous function by using the `async` keyword, like I've done here:
```
void setUserNamePref() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
  }
```

*Although I do not do this in this example. I'd recommend trying to limit the number of times you get an instance of Shared Preferences. That way you can reduce the number of asynchronous calls you make. Separating getting an instance, and using the instance would also be a good idea.*

### Writing data to persistent storage
Now we are ready to read or write to our preferences! Let's start by writing to our preferences. Since we've done so much setup, writing is easy:
```
void setUserNamePref(String userName) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('userName', userName);
  }
```

The new code here is `prefs.setString('userName', userName);`
Our SharedPreferences object has a number of different set methods. One for each of the supported data types! Make sure when you are using these set methods that you choose the right one for your use case. In this example, userName is a String so I can use `prefs.setString`.

### Reading from persistent storage

Now that we have data in storage, let's read it! By slightly modifying the example we've been working with, I can achieve this pretty easily:
```
Future<String> getUserNamePref() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.getString('userName');
  }
```

Again in this example, we are dealing with asynchronous functions so we need to return a `Future` and mark our function definition with `async`. 

Yay! We're done, right? 
Well, not quite, there's one more important thing to think about when getting a shared preference. What if userName doesn't exist yet? What if we've never stored a userName for this user before, and now we try to access it?

Well we can protect ourselves against this by using some of the new null safety features. See this example:
```
Future<String> getUserNamePref() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getString('userName') ?? 'Carl';
  }
```

If the key `'userName'` doesn't exist, we can instead return the String 'Carl' so that the program can proceed!



##Wrap up
Using shared_preferences can be really powerful. You can use it to store data about the app settings, like whether the user has selected to use dark mode. Also, since it supports storing Strings, you can serialize your dart objects into JSON and store them! Then when you want to use them you can deserialize them back into their objects! There are so many different ways to use shared preferences, that it's a really flexible way to store simple user data in a fast efficient way.



Thanks so much for getting this far! Hopefully you've enjoyed this brief look into the shared_preferences package! Make sure to follow if you're interested in more Flutter Package Previews!

Carl