Introduction
In mobile applications, some data has to be persisted to make the application startup faster, reduce network traffic or handle data completely offline. When we talk about data storage solutions for android, it is very common to think of SharedPreferences, it is a very simple/fast way of persisting data in our app and it has been here for a while, but now Jetpack DataStore comes as a possible replacement for SharedPreferences and itâs shortcomings.
In this article, we will be exploring Jetpack DataStore to store data in our Android application.
What is Jetpack DataStore?
Googleâs definition:
âJetpack DataStore is a data storage solution that allows you to store key-value pairs or typed objects with protocol buffers. DataStore uses Kotlin coroutines and Flow to store data asynchronously, consistently, and transactionally.â
DataStore provides 2 different implementations of Datastores:
- Preferences DataStore
- Proto DataStore
In short, the first one is the same as how SharedPreferences work, it is simpler to implement but has no type-safety. The second one uses protocol buffers to serialize the data, it has a more complex implementation, but it comes with many advantages.
Preferences vs Proto DataStore
The main objective of Proto DataStore is similar to Preferences DataStore, but the Proto DataStore is able to store objects with custom data types, it does not use key-value pairs like Preferences DataStore, just returns the generated object in a Flow. The generated objectâs type and structure depend on the schema of the .protoc file.
A few key features of Proto DataStore over Preferences DataStore are as follows:
- Provides type safety out of the box
- Able to define list inside protoc schema with repeated marked fields
- Requires learning of a new serialization mechanism, which depends on Protobuf but it is worth the effort.
- Protobuf is faster than XML and JSON serialization formats
Proto DataStore vs Room
If Proto DataStore is able to store objects with custom data types then you might be thinking âWhat to use Proto DataStore or Room?â or âWhy not use Room?â. Well if you use Room to save only userâs data, you need to create a database with a table, and also need to implement the query and insert functions. It sounds really inconvenient, so in this case, the Proto DataStore can be a hassle-free approach.
In this article, we will be discussing and focusing on the Preferences DataStore and how to implement it.
Why Jetpack DataStore?
âIf youâre currently using SharedPreferences to store data, consider migrating to DataStore instead.â – by Google
DataStore aims to replace SharedPreferences as it is thread-safe and non-blocking. The concept behind DataStore is also quite similar to SharedPreferences, it uses key-value pairs to store data. Following are the benefits of using DataStore over SharedPreferences:
Implementation (Preferences DataStore)
Itâs time to get into the implementation part and see how to use Preferences DataStore in our application.
Step 1: Dependencies
To use Jetpack DataStore in our application we have to add the dependency in our app-level build.gradle file:
implementation “androidx.datastore:datastore-preferences:1.0.0”
Step 2: Create a DataStore
To create a Preferences DataStore, we can use the preferenceDataStore delegate. The delegate will ensure that we have a single instance of DataStore with that name in our application.
Step 3: Create keys to the DataStore
Unlike SharedPreferences where you can use hard-coded string keys to write and read the data, DataStore requires key objects. We will need to create a key object and this is how we can create it:
This looks like an extra step but it is actually very helpful as your project becomes bigger, this will enforce developers to have all the keys in a centralized location.
You can also create other types of PreferenceKeys:
- booleanPreferenceKey(name: String)
- doublePreferenceKey(name: String)
- floatPreferenceKey(name: String)
- intPreferenceKey(name: String)
- longPreferenceKey(name: String)
- stringPreferenceKey(name: String)
- stringSetPreferenceKey(name: String)
Step 4: Write data to the DataStore
Now that we have created our DataStore and PreferencesKey, itâs time to write data to the DataStore, we need to call the edit() method, letâs see how we can do that:
Step 5: Reading data from DataStore
To read the data from DataStore, we need to access the âdataâ property from the datastore, the data property is a Flow<Preferences>, so we can either get the entire preferences or map it into the value we actually want:
Step 6: Handle Exceptions
With the flow object we can also catch exceptions:
Migrating from SharedPreferences
In order to be able to migrate from SharedPreferences to DataStore, we need to update the datastore builder to pass in a SharedPreferencesMigration to the list of migrations. DataStore will be able to migrate from SharedPreferences to DataStore automatically, for us. Migrations are run before any data access can occur in DataStore.
Import SharedPreferencesMigration from androidx.datastore.preferences
Thatâs it! Itâs that easy to migrate your data from SharedPreferences to DataStore. đ
Conclusion
Ideally DataStore is best to use with Kotlin and especially with coroutines. We donât need to worry about if our application uses standard SharedPreferences because migration is provided by the DataStore API.
Because of the fact that DataStore handles data migration, guarantees data consistency, and handles data corruption, it is worth changing from SharedPreferences to DataStore.
Feel free to share your responses and feedback below.
Thanks for reading!