Introduction
You may come across a requirement in your app to store some configuration (not that big to use Room).
For example, the previous UI mode - (Dark/Light)
You might come across Shared Preferences for this requirement. Shared Preferences are used to persist data of key-value pairs.
I agree that shared preferences work fine but are still way too old. Imagine if you want to observe the live changes of a preference value. you can't.
DataStore
DataStore is a part of Jetpack libraries that lets you store data of key-value pairs or typed objects in the device.
Types
Preferences DataStore - Stores key-value pairs
Proto DataStore - Stores typed objects using protocol buffers.
In this guide, we will learn about the Preferences DataStore.
Proto DataStore is for another day.
Why you should use DataStore instead of Shared Preferences?
- Credits: Android Developers Blog
Guide
Setup
Add the datastore preference in your grade dependency
dependencies {
implementation "androidx.datastore:datastore:1.0.0"
}
Build DataStore
Create a preference data store as an extension of context using the preferencesDataStore
delegate in the top level of a Kotlin file.
The name
of the Preferences DataStore is a mandatory parameter.
This ensures that a single instance of DataStore is created for the application process.
// Top level of any kotlin file.
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "configs")
Create Preference Keys
To store key-value pairs, we have to create keys for the preferences.
object PreferenceKeys {
val booleanKey = booleanPreferencesKey(name = "key_for_bool_value")
val byteArrayKey = byteArrayPreferencesKey(name = "key_for_byte_array_value")
val doubleKey = doublePreferencesKey(name = "key_for_double_value")
val floatKey = floatPreferencesKey(name = "key_for_float_value")
val intKey = intPreferencesKey(name = "key_for_int_value")
val longKey = longPreferencesKey(name = "key_for_long_value")
val stringKey = stringPreferencesKey(name = "key_for_string_value")
val stringSetKey = stringSetPreferencesKey("key_for_string_set_value")
}
Write data
Write a value to the preferences with the following code.
suspend fun writeValue(key: Preferences.Key<Int>, value: Int) {
context.dataStore.edit { preferences ->
// Set the new value to the preference.
preferences[key] = value
}
}
Write a value from a fragment or activity
// In an activity or fragment
// You can use any CoroutineScope other than lifeCycleScope.
lifeCycleScope.launch {
writeValue(key = intKey, value = 17)
}
Read data
Read value from the preferences with the following code.
It returns a Flow.
fun readValue(key: Preferences.Key<Int>, defaultValue: Int): Flow<Int> {
return context.dataStore.data.map { preferences ->
preferences[key] ?: defValue
}
}
Collect the value from the Flow
// In an activity or fragment
// You can use any CoroutineScope other than lifeCycleScope.
lifeCycleScope.launch {
readValue(key = intKey, defaultValue = 0).collect { value ->
// Utilize the value here
}
}
Bonus
Extension function to work with all types of keys.
/***
*
* An Extension function to DataStore<Preference>.
* Generic way to getting preference value from the data store.
* Returns preference value for the @param key if found,
* Otherwise it returns @param defValue
*
* @param key Preference key
* @param defValue default value if the preference key is not found
*
* @return a Flow of type T
*/
fun <T> DataStore<Preferences>.getValue(
key: Preferences.Key<T>,
defValue: T
): Flow<T> {
return data.map { preferences ->
preferences[key] ?: defValue
}
}
/***
*
* An Extension function to DataStore<Preference>
* Generic way to editing preference value from the data store.
* Edit the value of the preference @param key with @param value.
*
* @param key Preference key
* @param value Value need to be set to the given key
*
*/
suspend fun <T> DataStore<Preferences>.setValue(
key: Preferences.Key<T>,
value: T
) {
edit { preferences ->
preferences[key] = value
}
}
That's it for today.
Please do like if it helped you.
Comment if you have any queries.
Share if you want to help others.
For more articles like this, Do follow.
Thanks for reading. <3