Data Persistence on Flutter
See how to persist data to storage in a Flutter app, including to files and to a remote datastore, and use a Repository interface for the persistence. By JB Lorenzo.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Data Persistence on Flutter
30 mins
- Getting Started
- What Kind of Persistence Can You Use
- Serialized Data and Encryption
- Saving Data to Memory
- Flutter Persistence Options
- Persisting Data in a Key-Value Store
- Saving Plain Text with Key-Value Store
- Reading Plain Text with Key-Value Store
- Swapping out the Persistence Layer
- Removing Plain Text with Key-Value Store
- Saving Image with Key-Value Store
- Saving Objects into a Key-Value Store
- Persisting Data in Disk with Files
- Saving Your Data to Files
- Getting Strings, Images, and Objects from Files
- Persisting Data Online
- Saving Your Data Online
- Reading Your Data Online
- Removing Your Data Online
- Where to Go From Here?
It’s really hard to use an app if you have to login every time you use it. Also, it is difficult if you have to reenter your data every time you use it. Thus you have to really be determined, or rather persistent, in using this particular app that always forgets you and your data. :]
In order to avoid frustrating users, your app needs to save data that survives an app restart. Saving app data to some type of storage that survives app restarts is called data persistence.
In this Flutter tutorial, you’ll:
- Build an Alchemy-themed shopping app that persists data on different levels.
- Learn to use Flutter’s
File
package. - Perform persistence on text, images, and classes.
- Learn about the theory behind which persistence method to use.
- Implement persistence on disk and online.
Getting Started
Download the starter project by clicking on the Download Materials button at the top or bottom of the tutorial. Then, open the starter project in Android Studio 3.5 or later. You can also use VS Code, but you’ll have to adapt instructions below as needed.
You should use a recent version of Flutter, 1.7 or above. Make sure to get Flutter dependencies for the project if prompted to do so by Android Studio with a ‘Packages get’ has not been run message.
Looking at the starter code, you’ll find the starter project provides the interface and some logic for the shopping app already.
Try building and running the starter project. If you encounter issues running the project on iOS, try running pod install && pod update
in Terminal at the project root. You should see the shopping cart application with a screen asking for a username, like below.
Choose a username and photo (you may need to download a photo in your emulator or simulator browser first). Then after you log in, you should see the alchemical items available to be purchased.
Next, try using the app, e.g. adding some items to your cart. Afterwards, restart the app and you should see that you are being asked again for a username and all your shopping cart items are gone.
The app has lost your user’s data, and you will now learn how to fix this by implementing persistence.
What Kind of Persistence Can You Use
Before you can save data onto a persistence layer, you need to encode it. Typically, representations such as a string or an array of bytes are needed because persistence layers do not usually know how to handle your classes or objects.
Serialized Data and Encryption
Serialization is a way to convert a data structure, e.g. user data or an item in your shopping cart, into a string or a byte array. You will need to know how this concept works before heading into the topic of persistence. You can read about Google’s official documentation on serialization here.
Additionally, sometimes you want to protect the data you have serialized from being human readable. You can do this with encryption. There are no official docs about encryption for flutter but there are several plugins that exist. Check out these packages: encrypt, and flutter_string_encryption.
Saving Data to Memory
Once you have serialized your data, you need to know that saving it as a variable in memory does not achieve true persistence. While the app is running, the data is kept in memory, but once you restart the app, it’s gone. If you do not have another source of data, the data is lost. In contrast, saving it to disk lets you load the data again after a restart.
Flutter Persistence Options
The persistence options you have on Flutter include:
- Key-Value Store
- File storage
- Local database using SQLite
- Remote datastore
You’ll investigate three of these options in this tutorial. Saving data locally to an app database using SQLite will be left for another tutorial.
Persisting Data in a Key-Value Store
There’s multiple ways to store data in disk. For instance, one of them is using a key-value store. Accordingly, iOS and Android has native solutions for doing key-value storage in disk. Specifically, iOS has UserDefaults and Android has SharedPreferences. Instead of manually using each of them, you can use an existing Flutter package called shared_preferences that uses the appropriate one depending on the platform on which you are running.
Saving Plain Text with Key-Value Store
With this in mind, you can try storing plain text into disk using a key-value storage. Open the file lib/data/LocalKeyValuePersistence.dart. Add the _generateKey
method below then go to the method saveString
to add these lines:
// 1
String _generateKey(String userId, String key) {
return '$userId/$key';
}
@override
void saveString(String userId, String key, String value) async {
// 2
final prefs = await SharedPreferences.getInstance();
// 3
await prefs.setString(_generateKey(userId, key), value);
}
Click on SharedPreferences
and hit option+return on Mac or Alt+Enter on PC to add the needed import.
In the above, you (1) add a method to generate a key from a user’s id and a key. Then (2) when saving, you get the instance for SharedPreferences
. Lastly (3), you store a key-value pair onto disk using the shared_preferences
Flutter plugin. The _generatedKey>
method is called to make a new key for storing the string.
Reading Plain Text with Key-Value Store
Although you are now able to write a string using the key-value storage, you also need the ability to read it back. With this in mind, update getString
to be the following:
@override
Future<String> getString(String userId, String key) async {
// 1
final prefs = await SharedPreferences.getInstance();
// 2
return prefs.getString(_generateKey(userId, key));
}
You are (1) again getting an instance of the SharedPreferences
class from the Flutter plugin. Then (2) you are calling the getString
method to return the previously stored value by providing key
.