1. What is DataStore

Jetpack DataStore is a data storage solution that allows the use of protocol caches to store key-values or serialized objects. Google suggests that if you are currently using SharedPreferences, consider migrating to DataStore.

Datastores are of two types: Preferences DataStore and Proto DataStore.

  • Preferences DataStore: Uses keys to store and access data. This implementation does not require a predefined schema and does not ensure type safety.
  • Proto DataStore: Stores data as instances of custom data types. This implementation requires you to define schemas using protocol buffers, but ensures type safety.

2.Preferences DataStore

2.1 import library

Add the following dependencies to the Gradle file according to your personal needs.

// Typed DataStore (Typed API surface, such as Proto)
dependencies {
  implementation "Androidx. Datastore: datastore: 1.0.0 - alpha07"

  // optional - RxJava2 support
  implementation "Androidx. Datastore: datastore - rxjava2:1.0.0 - alpha07"

  // optional - RxJava3 support
  implementation "Androidx. Datastore: datastore - rxjava3:1.0.0 - alpha07"
}
// Alternatively - use the following artifact without an Android dependency.
dependencies {
  implementation "Androidx. Datastore: datastore - core: 1.0.0 - alpha07"
}
Copy the code

2.2 Creating the Preferences DataStore

First we need to create an instance of the Preferences DataStore. We can create an instance of DataStore

using a property delegate as shown in the following code. The preferred approach is to create the instance at the top of the Kotlin file so that it can be easily invoked within the application. In addition, if the current project using Rxjava is the case, you need to use the RxPreferencesDataStoreBuilder to create.

val dataStore: DataStore<Preferences> = createDataStore(
    name = DATA_STORE_KEY
)
Copy the code

2.3 Reading content from the Preferences DataStore

To read the content, we need to use a specific Key based on the attributes of the content. The following code calls the stringPreferencesKey method when the content is String.

val textKey = stringPreferencesKey(MainActivity.DATA_STORE_TEXT_KEY)
Copy the code

It then passes the Key to the DataStore instance to read the data contents.

    // read data
    fun getText(dataStore: DataStore<Preferences>) {
        viewModelScope.launch(Dispatchers.IO) {
            val textKey = stringPreferencesKey(MainActivity.DATA_STORE_TEXT_KEY)
            dataStore.edit { settings ->
                val text = settings[textKey]
                textLiveData.postValue(text)
            }
        }
    }
Copy the code

2.4 Writing content to the Preferences DataSotre

Writing content is similar to reading content. Just look at the code!

    // store data
    fun saveText(dataStore: DataStore<Preferences>, content: String) {
        viewModelScope.launch(Dispatchers.IO) {
            val textKey = stringPreferencesKey(MainActivity.DATA_STORE_TEXT_KEY)
            dataStore.edit { settings ->
                settings[textKey] = content
            }
        }
    }  
Copy the code

2.5 Screenshot

3. Proto DataStore

The Proto DataStore implementation uses DataStore and protocol buffers to keep typed objects on disk. In other words, you can store custom classes.

3.1 Defining the Architecture

First, we need to create the predefined schema in a proto file in a directory with a path of app/ SRC /main/proto. For details on how to use the Protobuf language, see here.

The code for the predefined schema in the example I wrote is as follows.

syntax = "proto3";

option java_package = "com.example.datastoredemo";
option java_multiple_files = true;

message DataModelPreference {
  string name = 1;
  int32 age = 2;
}
Copy the code

In short, you need to modify the JavA_Package to your project path, and you need to write the data structures you want to customize.

3.2 Creating a Data Model

We need to create a data model that is identical to the data structure in the predefined structure. If you want default values in the Proto DataStore, you can set the default values in the Data Model.

data class DataModel(
    val name: String? = "1".val age: Int? = 1
)
Copy the code

3.3 create a Serializer

Next, we need to create a Serializer. We need to inherit from Serializer and override some methods. The specific code is as follows. Note that the DataModelPreference in Serializer should be the same as the data structure defined in the predefined schema.

object DataModelSerializer : Serializer<DataModelPreference> {
    override fun readFrom(input: InputStream): DataModelPreference {
        try {
            return DataModelPreference.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override fun writeTo(t: DataModelPreference, output: OutputStream) {
        t.writeTo(output)
    }

    override val defaultValue: DataModelPreference
        get() = DataModelPreference.getDefaultInstance()
}
Copy the code

3.4 Creating a DataStore Instance

Use the context.createdatastore () extension function to create an instance of DataStore

. Of course, T is the DataModelPreference, the data type defined in the predefined schema. Pass the name of the data file to save to fileName. Note that the file type is PB.

private val datastore: DataStore<DataModelPreference> = createDataStore(
    fileName = PROTO_DATA_FILE_NAME,
    serializer = DataModelSerializer
)
Copy the code

3.5 Reading Data from the Proto DataStore

Use datasotre. data to read data from the stored object and return it in Flow form. The important thing to note here is that the IO thread must be used, otherwise the UI will stall.

    fun getText(dataStore: DataStore<DataModelPreference>) {
        viewModelScope.launch(Dispatchers.IO) {
            dataModelFlow = dataStore.data.map { pref ->
                Log.d("AAAA"."name: ${pref.name} age: ${pref.age}")
                DataModel(pref.name, pref.age)
            }
        }
    }
Copy the code

3.6 Saving Data to the Proto DataStore

Use the datastore. update method to save or update data in the Proto DataStore.

    fun getText(dataStore: DataStore<DataModelPreference>) {
        viewModelScope.launch(Dispatchers.IO) {
            dataModelFlow = dataStore.data.map { pref ->
                DataModel(pref.name, pref.age)
            }
        }
    }
Copy the code

3.7 Screenshot

4. Others

Github:github.com/HyejeanMOON…

Easy to use Jetpack Compose tutorial

1. Compose’s programming idea

Jetpack tutorials

Jetpack Paging3 tutorial 2. Jetpack DataStore Tutorial 3. Android Jetpack Room Tutorial 4 The use of the WorkManager

Other tutorial

Dagger Hilt!! Scoped Storage for Android Scoped Storage (Scoped) for Android Scoped Storage (Scoped) Use of Google’s MergeAdapter