Hello DataStore, Bye SharedPreferences👋 — Android📱 — Part 1: Preference DataStore
In this article series, we’ll learn how to use the latest Android Jetpack 🚀 library i.e. DataStore in Android apps.
Welcome Android developers 👋. This article is the first part of a series article based on the new Jetpack library🚀 i.e. DataStore🗄️. Currently, it’s alpha version is released. Let’s see what’s DataStore and why DataStore.
What is DataStore 🤷♀️?
- Jetpack DataStore is a data storage solution.
- It allows us to store key-value pairs (like
SharedPreferences
) or typed objects with protocol buffers (We’ll see it in next article). - DataStore uses Kotlin, Coroutines and Flow to store data asynchronously with consistency and transaction support 😍.
- In short, it’s the new data storage solution which is the replacement of
SharedPreferences
.
Why DataStore 🤷♂️
- First and my favourite reason 😃 — Built with❤️ Kotlin, Coroutines and Flow.
- If you have used
SharedPreferences
you might abuse or blamed it for something 😆 thenDataStore
is here to rescue! SharedPreference
has some drawbacks like it provided synchronous APIs -but it’s not MAIN-thread-safe! whereas DataStore is safe to use in UI thread because it usesDispatchers.IO
under the hood👀.- It’s safe from runtime exceptions!❌⚠️. What would be more satisfying that? 😅
- It also provides a way to migrate from
SharedPreferences
😍. - It provides Type safety! (Using Protocol buffers).
These are some reasons which encourage us to use DataStore and finally say goodbye to beloved SharedPreferences
👋.
# That’s not only the reason —
DataStore
provides two different types of implementations to store data.
- Preference DataStore — This uses key-value pairs to store data. But it doesn’t provide type-safety :
- Proto DataStore — It stores data as a custom type with specified schema using Protocol Buffers (We’ll see about it in the next article).
I think that’s enough introduction to DataStore
. It’s time to write some code👨💻😎.
Let’s begin code 👨💻
You can simply clone or refer this repository to get example code demonstrating DataStore
📁.
We’ll develop a sample Android application which stores a UI mode preference from user i.e. 🌞 Light Mode or 🌑 Dark Mode.
First of all, let’s add a Gradle dependency in build.gradle
of your app module. Currently 1.0.0-alpha01
is the latest release. You can keep an eye here to get info about the latest version.
Start implementing DataStore 📁
- For UI mode preference i.e. Dark mode or Light mode, we’ll create an enum class as below
enum class UiMode {
LIGHT, DARK
}
- We’ll create a class —
SettingsManager
where we’ll be managing setting preferences set by users in our app.
This will initialize the instancedataStore
field by creating DataStore
using the file name as “settings_pref”. createDataStore()
is extension function created on Context
.
- Now we’ll be storing UI mode preference using a key (as we managed in
SharedPreference
). Key inDataStore
is created as below 👇
Here 👆 we’ve created a 🔑 KEY IS_DARK_MODE
which will store a boolean value (false
for Light mode / true
for Dark mode). Because Preferences DataStore does not use a predefined schema, you must use Preferences.preferencesKey()
to define a key for each value that you need to store in the DataStore<Preferences>
.
- Now we’ll create a method which will set UI mode from our UI/Activity i.e.
setUiMode()
🔧
Note: Preferences
DataStore
provides a methodedit()
which transactional updates value inDataStore
.
- Now it’s time to get preference 🔥.
DataStore
providesdata
property which exposes the preference values usingFlow
. Means it’s time to leverage Flow 🌊 😍. See the code below 👇
👆 You can see we’ve exposed a Flow uiModeFlow
which will emit values whenever preferences are edited/updated. If you remember, we have been storing boolean in our DataStore
. Using map{}
, we’re mapping boolean values to theUiMode
i.e UiMode.LIGHT
or UiMode.DARK
.
Note: DataStore throws
IOException
when it failed to read a value. So we have handled it by emittingemptyPreferences()
.
So that’s all about setting up DataStore
😃. Now let’s design UI.
Setup Activity
In this activity, We have just an ImageButton
which will have image resources i.e. 🌞 and 🌘 based on UI mode.
- In
initViews()
we’ll update preferences (UI Mode) on click ofImageButton
.
- In
observeUiPreferences()
, we’ll observeDataStore
UI Mode preference using a field which we exposed inSettingsManager
which is aFlow
🌊 which will emit values whenever preferences are updated.
👆 Here we’ve used asLiveData()
flow extension function which gives emitted values from Flow in LiveData
. (Otherwise, we can also use lifecycleScope.launch{}
here if you don’t like to use LiveData
).
- We’re just updating image resource and background color of root layout when UI mode is changed. (Actual mode can be changed using
AppCompatDelegate.setDefaultNightMode()
)
Yeah! That’s it 😃. It’s time to run this app 🚀. When you run this app, you’ll see it like 👇
Looking Awesome! 😍, isn’t it?
This is how we implemented Preferences DataStore
instead of SharedPreferences
.
So, DataStore
is cool 🆒, isn’t it? Give it a try 😃. Since it’s currently in alpha, maybe many more is on the way to come 🛣️.
DataStore uses file management mechanism for storing data. But it’s different than managed in SharedPreferences
. Now if you want to see how’s your data getting stored then using Android Studio’s ‘Device File Explorer’ you can go to /data/app/YOUR_APP_PACKAGE_NAME/files/datastore
and you can see the file there like below 👇.
But it’s content is not readable as you can see in below image 👇
Let me know your valuable feedback about this article. 🙏
In the next article, we’ll see how to use Proto DataStore.
Thank you! 😃