Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jetpack DataStore

Jetpack DataStore

Divya Jain

April 25, 2022
Tweet

More Decks by Divya Jain

Other Decks in Programming

Transcript

  1. Nom de la partie - Persist Key-value pairs of Simple

    data - Single Instance of the class, shared by all clients - Easy methods to read-write from Shared preferences - Special editor to make modifications - Read/write operations are on the main thread
  2. override fun getUser(): User { val firstName = sharedPref.getString(PREF_FIRST_NAME, "")

    val lastName = sharedPref.getString(PREF_LAST_NAME, "") return User(firstName = firstName ?: "", lastName = lastName ?: "") } override fun saveUser(user: User) { with (sharedPref.edit()) { putString(PREF_FIRST_NAME, user.firstName) putString(PREF_LAST_NAME, user.lastName) apply() } }
  3. Nom de la partie - No Error handling mechanism -

    No Type Safety - Blocks UI Thread - Inconsistent data in the app
  4. Nom de la partie - Data storage solution - Store

    Key-value pairs or Typed objects - Uses coroutines/flows to store data asynchronously - Uses protocol buffers to store data - Transactional, consistent data operations - Two different implementations Preferences DataStore Proto DataStore
  5. Nom de la partie Preferences DataStore - Modern replacement for

    SharedPreference API - Key-Value pairs to store data, no type safety - No predefined schéma implementation "androidx.datastore:datastore-preferences:1.0.0-beta01" private val Context.userPreferencesDataStore:DataStore<Preferences> by preferencesDataStore(name = "user")
  6. private val USER_FIRST_NAME = stringPreferencesKey("user_first_name") private val USER_LAST_NAME = stringPreferencesKey("user_last_name")

    override suspend fun saveUserToPreferencesStore(user: User) { userPreferencesDataStore.edit { preferences -> preferences[USER_FIRST_NAME] = user.firstName preferences[USER_LAST_NAME] = user.lastName } } override fun getUserFromPreferencesStore(): Flow<User> = userPreferencesDataStore.data .map { preferences -> User( firstName = preferences[USER_FIRST_NAME] ?: "", lastName = preferences[USER_LAST_NAME] ?: "" ) }
  7. Nom de la partie Why preference Datastore over SharedPreferences -

    Safe Asynchronous call over Dispatchers.IO - No apply/commit to save changes - Transactional updates - Exposes data through a Flow - Solid error handling support/no random runtime exceptions
  8. Nom de la partie Proto DataStore - Store and access

    custom typed objects - Predefined Schema in .protoc file - Out of the box type safety - Uses protocol buffers as serialization mechanism implementation "androidx.datastore:datastore:1.0.0-beta01"
  9. syntax = "proto3"; option java_package = "com.djain.protodatastoresample"; option java_multiple_files =

    true; message UserPreference { string first_name = 1; string last_name = 2; } .proto file - app/src/main/proto/
  10. object UserSerializer : Serializer<UserPreference> { override val defaultValue: UserPreference =

    UserPreference.getDefaultInstance() override suspend fun readFrom(input: InputStream): UserPreference { try { return UserPreference.parseFrom(input) } catch (exception: InvalidProtocolBufferException) { throw CorruptionException("Cannot read proto.", exception) } } override suspend fun writeTo(t: UserPreference, output: OutputStream) = t.writeTo(output) }
  11. private val Context.userProtoDataStore: DataStore<UserPreference> by dataStore( fileName = "user.pb", serializer

    = UserSerializer ) override suspend fun saveUserToProtoStore(user: User) { userProtoDataStore.updateData { currentUserData -> currentUserData.toBuilder() .setFirstName(user.firstName) .setLastName(user.lastName) .build() } }
  12. Nom de la partie val dataStore = context.createDataStore( name =

    USER_PREFERENCES_NAME, migrations = listOf(SharedPreferencesMigration(context, USER_PREFERENCES_NAME )) ) SharedPreferences Migration