Android Tutorial
Software Setup and Configuration
Android Studio
File Structure
Components
Core Topics
Layout
View
Button
Intent and Intent Filters
Toast
RecyclerView
Fragments
Adapters
Other UI Component
Image Loading Libraries
Date and Time
Material Design
Bars
Working with Google Maps
Chart
Animation
Database
Advance Android
Jetpack
Architecture
App Publish
App Monetization
DataStore
is a modern data storage solution introduced by Google that comes as a replacement for SharedPreferences
in Android. While SharedPreferences
is a way to store key-value pairs, DataStore
is more robust and offers more flexibility, such as type-safety and asynchronous operations using Kotlin coroutines.
There are two types of DataStore
:
SharedPreferences
).Here, I'll show you how to use the Preferences DataStore:
Add the required dependencies to your build.gradle
:
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha01"
Ensure you have the latest version.
You can create an instance of DataStore
using the Context
:
val dataStore: DataStore<Preferences> = context.createDataStore( name = "settings" )
Reading from the DataStore
is asynchronous:
val EXAMPLE_KEY = preferencesKey<String>("example_key") val exampleFlow: Flow<String?> = dataStore.data .map { preferences -> // Return the value or null if not set preferences[EXAMPLE_KEY] }
To observe this data in a UI, you can collect it:
lifecycleScope.launch { exampleFlow.collect { value -> // Use the value } }
Writing to DataStore
is also asynchronous:
suspend fun saveString(key: Preferences.Key<String>, value: String) { dataStore.edit { preferences -> preferences[key] = value } }
You'd call this function from a coroutine:
lifecycleScope.launch { saveString(EXAMPLE_KEY, "This is an example") }
DataStore also provides utilities to migrate from SharedPreferences
:
val dataStore: DataStore<Preferences> = context.createDataStore( name = "settings", migrations = listOf( SharedPreferencesMigration(context, "legacy_preferences_name") ) )
SharedPreferences
.Remember, as with any new library, always refer to the official documentation to understand the full capabilities and best practices.
Preferences DataStore example code Android:
// Create a DataStore instance val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings") // Write data to DataStore dataStore.edit { preferences -> preferences[KEY_NAME] = "John Doe" preferences[KEY_AGE] = 25 } // Read data from DataStore val nameFlow: Flow<String?> = dataStore.data.map { preferences -> preferences[KEY_NAME] ?: "" } // Observe changes in data nameFlow.collect { name -> Log.d(TAG, "Name: $name") }
Migrating from SharedPreferences to DataStore in Android:
Update your code by replacing SharedPreferences
with DataStore
. Use the edit
function to write data and observe changes using Flow
.
Working with key-value pairs in Preferences DataStore:
Use key-value pairs for storing and retrieving data:
// Write data dataStore.edit { preferences -> preferences[KEY_USER_ID] = "123" } // Read data val userId: Flow<String?> = dataStore.data.map { preferences -> preferences[KEY_USER_ID] ?: "" }
Custom data types in Preferences DataStore Android:
Serialize and deserialize custom data types:
@Serializable data class UserProfile(val name: String, val age: Int) // Write custom data dataStore.edit { preferences -> preferences[KEY_USER_PROFILE] = UserProfile("John Doe", 25) } // Read custom data val userProfile: Flow<UserProfile?> = dataStore.data.map { preferences -> preferences[KEY_USER_PROFILE] }
Reading and writing data with Preferences DataStore:
Use the edit
function to write data and access data using the data
property. Combine with map
for transformations.
Preferences DataStore and Jetpack Navigation in Android:
Access DataStore
in different fragments or activities. Share the same DataStore
instance to maintain consistency across the app.
Preferences DataStore and Kotlin Coroutines:
Use coroutines to perform asynchronous operations with DataStore
. Wrap data access operations with withContext(Dispatchers.IO)
.
Preferences DataStore with encrypted preferences in Android:
Use Android's EncryptedSharedPreferences
or consider encrypting the data before storing it in DataStore
for enhanced security.
Preferences DataStore and LiveData integration:
Convert Flow
to LiveData
for easier integration with UI components:
val userIdLiveData: LiveData<String?> = userId.asLiveData()
Handling data changes with Preferences DataStore:
Use the collect
function on the Flow
to observe changes in the data:
nameFlow.collect { name -> Log.d(TAG, "Name: $name") }