Android Jetpack Data Store: A Comprehensive Guide to Modern Data Storage

Süleyman Başaranoğlu
3 min readFeb 6, 2022

Introduction

Hello everyone! In this article, we will explore Jetpack Data Store and even build a simple application to demonstrate its capabilities. While discussing Data Store, it’s essential to also remember other Android data storage methods like Shared Preferences and Room.

Data Storage

What is Data Store?

Data Store is a modern storage solution from Android that utilizes Key-Value pairs similar to Shared Preferences. It also incorporates Flow and Coroutines for better performance and efficiency.

Note: In Pro versions, DataStore can generate a schema based on the objects you define.

_getPreferences.getString("foodName", foodName)
key value

Types of Storage Keys

The Android Developer site provides us with different types of storage keys:

  • booleanPreferencesKey
  • doublePreferencesKey
  • floatPreferencesKey
  • intPreferencesKey
  • longPreferencesKey
  • stringPreferencesKey
  • stringSetPreferencesKey
Data Storage

Why Use Data Store?

Here are some advantages of using Data Store:

  • Runtime Exception Safety: Data Store minimizes runtime exceptions.
  • Success and Error Handling: When setting data, you can easily handle both success and error cases.
  • Read and Write: Data Store allows for both reading and writing of data.
  • Asynchronous Programming: With the use of Flow and Coroutines, asynchronous programming becomes seamless.
  • Type Safety: If you’re using Pro DataStore, the compiler will enforce type safety for you.

Coding Time

Dependencies

implementation("androidx.datastore:datastore-preferences:1.0.0")implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"

Creating a Simple Product App

Our sample app will include the following fields:

  • Product Name (String)
  • Product Price (Int)
  • Is Sold (Boolean)

First, let’s create a class to manage DataStore:

Create variable for for use data store.

private val Context.datastore: DataStore<Preferences> by preferencesDataStore("products")private val myDatastore: DataStore<Preferences> = context.datastore

For Key

val PRODUCT_NAME= stringPreferencesKey("PRODUCT_NAME")
val PRODUCT_PRICE= intPreferencesKey("PRODUCT_PRICE")
val IS_SOLD = booleanPreferencesKey("IS_SOLD")

I will use Coroutine and create suspend functions

suspend fun storeProductData(
productName: String,
productPrice: Int,
isSold: Boolean
) {
myDatastore.edit { preferences ->
preferences[PRODUCT_NAME] = productName
preferences[PRODUCT_PRICE] = productPrice
preferences[IS_SOLD] = isSold
}
}

For Flow

val productNameFlow: Flow<String> = myDatastore.data.map {
it[PRODUCT_NAME] ?: ""
}

val productPriceFlow: Flow<Int> = myDatastore.data.map {
it[PRODUCT_PRICE] ?: 0
}

val productIsSoldFlow: Flow<Boolean> = myDatastore.data.map {
it[IS_SOLD] ?: false
}
Manager.kt

VİEW

Page 1 (Save Data)

XML PAGE 1
val isSold: Boolean = _binding.switchIsSold.isChecked

I made a suspend function for Coroutine in our manager file above, let’s call it here and get our data from the UI.

CoroutineScope(Dispatchers.IO).launch {
_productManager.storeProductData(
_binding.etProductName.text.toString(),
_binding.etProductPrice.text.toString().toInt(),
isSold
)
}
Save Data

Page 2 (Observe Data)

The general observe code structure will be as follows. asLiveData helps us to Observe.

_productManager.productNameFlow.asLiveData()
.observe(this) { productName ->
productName?.let {
_binding.tvProductName.text = productName
}
}

or

lifecycleScope.launchWhenStarted {
_productManager.productSellingLocationFlow.collect{
location ->
location?.let {
_binding.etCreateLocation.setText(location)
}
}
}
Observe Data

App Demo

Thanks

https://developer.android.com/topic/libraries/architecture/datastore

--

--