Skip to content

Latest commit

 

History

History

swissknife-datastore

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

DataStoreSource

It contains a Custom DataStoreSource that provides the ability to store custom entities types without the requirement of using Protocol Buffers.

Jetpack DataStore provides two implementations, one that stores key-value primitives types and another to stores typed objects with protocol buffers. This library provides a DataStore implementation that enables storing typed objects, just providing a DataStoreEntitySerializer.

The DataStoreEntitySerializer is an interface with two methods, one to serialize an entity from a string and the other to serialize the entity into a string.

interface DataStoreEntitySerializer {
  @WorkerThread
  fun <T> toString(t: T, aClass: Class<T>): String

  @WorkerThread
  fun <T> fromString(value: String?, aClass: Class<T>): T?
}

You can choose what serializer do you prefer, for example, if you are using Gson you could define a GsonSerializer like this:

class GsonDataStoreEntitySerializer(private val gson: Gson = Gson()) : DataStoreEntitySerializer {
  override fun <T> toString(t: T, aClass: Class<T>): String = gson.toJson(t)

  override fun <T> fromString(value: String?, aClass: Class<T>): T? = gson.fromJson(value, aClass)

After you have created the serializer, you can use the DataStoreSource. To create a DataStoreSource, you need to provide a Jetpack DataStore, a DataStoreEntitySerializer and a [CoroutineDispatcher ] to specify where you want to run the background tasks.

  private val dataStoreSource = DataStoreSource(
      dataStore = context.createDataStore(name = "my-data-store"),
      serializer = GsonDataStoreEntitySerializer()
  )

The DataStoreSource provides three methods to manage the data:

  inline fun <reified T> getEntity(key: String): Flow<T?> = getEntity(key, T::class.java)
  
  suspend inline fun <reified T> putEntity(key: String, t: T) = putEntity(key, t, T::class.java)

  suspend inline fun <reified T> removeEntity(key: String) = removeEntity(key, T::class.java)

After that you can create a storage to use the DataStoreSource. In the sample app, it's defined a SessionRepository which manages the app's session information.

private const val DATA_STORE_NAME = "data_store_name"
private val Context.appSessionDataStore: DataStore<Preferences> by preferencesDataStore(name = DATA_STORE_NAME)

class SessionRepository(context: Context) {
  companion object {
    private const val SESSION_REPOSITORY_KEY = "session"
  }

  private val dataStore = DataStoreSource(
      context.appSessionDataStore(),
       GsonDataStoreEntitySerializer()
  )

  val session: Flow<Session?>
    get() = dataStore.getEntity(SESSION_REPOSITORY_KEY)

  suspend fun saveSession(session: Session?) =
      dataStore.putEntity(SESSION_REPOSITORY_KEY, session)
}

Dependencies: