I've recently been working with Jetpack Compose in a mobile project. If you don't know what it is, I suggest you watch this.
In all the apps I've developed, it is always required to save some information in the local memory, such as the user's preferences or username.
The Shared Preference seems to be the most correct choice in this case.
But if we use a Jetpack compose, we must not use them.
Use a DataStore ✨
In order to use DataStore correctly always keep in mind the following rules:
Never create more than one instance of DataStore for a given file in the same process.
The generic type of the DataStore must be immutable.
Never mix usages of SingleProcessDataStore and MultiProcessDataStore for the same file.
More detail here
Differences between Shared Preference and DataStore
Following the main differences
If you interessed at Proto DataStore read this
Implementation 🧑🏻💻
First of all, add the following to your Gradle file
implementation "androidx.datastore:datastore-preferences:1.0.0"
Let’s create an instance of a data store for storing and fetching data
class StoreData(private val context: Context) {
companion object {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("storeData")
val USERNAME = stringPreferencesKey("store_Data")
}
...
}
Create the methods fo read and write data into DataStore
val getData: Flow<String?> = context.dataStore.data
.map { preferences ->
preferences[USERNAME] ?: ""
}
suspend fun saveData(name: String) {
context.dataStore.edit { preferences ->
preferences[USERNAME] = name
}
}
Remember: DataStore use Async API, so if you want call saveData
use a kotlin's coroutine.
val scope = rememberCoroutineScope()
scope.launch {
dataStore.saveData(username.value)
}
Use this function if you want check if the key is in store
fun isKeyStored(key: Preferences.Key<String>): Flow<Boolean> =
context.dataStore.data.map {
preference -> preference.contains(key)
}
Sounds cool. But if you want save an object? A list for example? We need serialize the object.
I used the Gson
library.
Add to your Gradle file
implementation 'com.google.code.gson:gson:2.8.7'
then create the instance of Gson and the methods for read and write
private val gson: Gson = Gson()
suspend fun saveData(name: List<DataObject>) {
context.dataStore.edit { preferences ->
val jsonString = gson.toJson(name)
preferences[OBJECT] = jsonString
}
}
val getData: Flow<List<DataObject>> = context.dataStore.data
.map { preferences ->
val jsonString = preferences[OBJECT] ?: ""
gson.fromJson(jsonString, Array<DataObject>::class.java).toList()
}
So if you want check if data is in store and get object, use this
if(dataStore.isKeyStored(stringPreferencesKey("store_Data")).collectAsState(initial = false).value) {
dataStore.getData.collectAsState(initial = listOf(DataObject(x, y))).value.let {
myViewModel.setDataMethod(it)
}
}
and that's all.
See ya 👋🏻
Thank you for reading ✨
Top comments (2)
Thanks for this article. I'm wondering how to use this into Jetpack compose?
I mean what can I pass to StoreData class as context/
val context = LocalContext.current