In this post, I discuss, how to preserve user data either as files on the device, in key-value pairs, in a database, or with other data types, and share data between other apps and devices.
Android uses a file system that's similar to disk-based file systems on other platforms. The system provides several options for you to save your app data.
App-specific storage : Store files that are for your app's use only. Use the directories within internal storage to save sensitive information that other apps shouldn't access.
Shared storage: Store files that your app intends to share with other apps, including media, documents, and other files.
Preferences*: Store private, primitive data in key-value pairs.
Databases*: Store structured data in a private database using the Room library.
App-specific storage
https://developer.android.com/training/data-storage/app-specific#kotlin
Store a file:
val filename = "myfile"
val fileContents = "Hello world!"
context.openFileOutput(filename, Context.MODE_PRIVATE).use {
it.write(fileContents.toByteArray())
}
Access a file:
context.openFileInput(filename).bufferedReader().useLines { lines ->
lines.fold("") { some, text ->
"$some\n$text"
}
}
Preferences
- SharedPreference
It stores data using key-value pairs. It can store primitive data type → boolean, float, double, int, String.
For use storing - user details, user setting, last score, location catching, multiple choice question.
Store a data:
private fun onSplashFinished(){
val sharedPref = requireActivity().getSharedPreferences("onBoarding", Context.MODE_PRIVATE)
val editor = sharedPref.edit()
//..
editor.putInt("age", 23)
editor.putBoolean("Finished", true)
editor.apply()
//.. or better use
editor.apply{
putInt("age", 23)
putBoolean("Finished", true)
apply()
}
}
Access a data:
private fun onBoardingFinished(): Boolean {
val sharedPref = requireActivity().getSharedPreferences("onBoarding",Context.MODE_PRIVATE)
val value = sharedPref.getBoolean("Finished", false)
return value
}
data a remove:
val sharedPref = this.getSharedPreferences("onBoarding", Context.MODE_PRIVATE)
sharedPref.edit().remove("splashFinished").apply()
- DataStore
DataStore is a new and improved data storage solution intended to replace SharedPreferences. Built on Kotlin and Flow coroutines Android provided by Jetpack library. DataStore advantages are like type safety, asynchronous APIs, and support for observing data changes.
Two kind of versions of data store you can use. The one is "Preferences datastore". Other kind is "proto datastore". So there are very similar but proto datastore is also typesafe, preferences datastore are not.
(i) Preferences datastore
It is well-suited for scenarios where you need to store a small amount of data and want to avoid the complexities of working with SharedPreferences.
implementation "androidx.datastore:datastore-preferences:1.0.0"
implementation "androidx.datastore:datastore-preferences-core:1.0.0"
Creating a Preferences DataStore
val dataStore: DataStore<Preferences> = context.createDataStore(name = "my_preferences")
Storing Data
// Writing data
dataStore.edit { preferences ->
preferences[booleanPreferencesKey("isFirstLaunch")] = true
preferences[intPreferencesKey("userScore")] = 100
}
// Writing data
suspend fun setExampleValue(newValue: String) {
dataStore.edit { preferences ->
preferences[EXAMPLE_KEY] = newValue
}
}
Retrieving Data
val isFirstLaunchFlow: Flow<Boolean> = dataStore.data.map { preferences ->
preferences[booleanPreferencesKey("isFirstLaunch")] ?: false
}
val userScoreFlow: Flow<Int> = dataStore.data.map { preferences ->
preferences[intPreferencesKey("userScore")] ?: 0
}
Data Storage in Android: SharedPreferences and Preferences DataStore
(ii)Proto datastore
ProtoDataStore is designed to store more complex.It's a good choice when you need to store custom objects or structured data that requires efficient serialization and deserialization.
val dataStore = context.createDataStore(name = "my_proto_preferences")
// Define a protobuf data class
@Serializable
data class UserData(val id: Int, val name: String)
// Reading data
val userData: Flow<UserData?> = dataStore.data
.map { preferences ->
preferences[USER_DATA_KEY]
}
// Writing data
suspend fun setUserData(newUser: UserData) {
dataStore.edit { preferences ->
preferences[USER_DATA_KEY] = newUser
}
}
Top comments (0)