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

DataStoreを導入してみた

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for kobaken kobaken
April 20, 2023

 DataStoreを導入してみた

Avatar for kobaken

kobaken

April 20, 2023
Tweet

More Decks by kobaken

Other Decks in Technology

Transcript

  1. Preferences DataStoreΛ࡞੒ val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = “settings") ⚠1ϑΝΠϧʹରͯ͠DataStoreͷΠϯελϯε͸γϯάϧτϯʹ͢Δ͜ͱ⚠

    →ಉϓϩηε্ʹॴఆϑΝΠϧʹରͯ͠ΞΫςΟϒͳDataStore͕ෳ਺͋Δͱ σʔλʹ৮ΕΔࡍʹIllegalStateExceptionΛεϩʔ͢Δ
  2. DataStoreͷinterfaceʢ࠶ܝʣ public interface DataStore<T> { public val data: Flow<T> public

    suspend fun updateData(transform: suspend (t: T) -> T): T }
  3. ಡΈऔΓ val COMIC_USER_IDS = stringSetPreferencesKey("comic_user_ids") val comicUserIdsFlow: Flow<Set<String>> = context.dataStore.data

    .map { preferences -> preferences[COMIC_USER_ID] ?: emptySet() } booleanPreferencesKey 
 intPreferencesKey longPreferencesKey fl oatPreferencesKey 
 stringPreferencesKey
  4. SharedPreferences→DataStore΁ͷҠߦ const val PREFERENCES_NAME = "..." val Context.dataStore by preferencesDataStore(

    name = PREFERENCES_NAME, produceMigrations = { context -> SharedPreferencesMigration( context = context, sharedPreferencesName = PREFERENCES_NAME, // ࢦఆͨ͠keyͷΈҠߦͰ͖ΔʂʢσϑΥϧτҾ਺͸MIGRATE_ALL_KEYSʣ keysToMigrate = setOf(Key.COMIC_USER_IDS) ) } )
  5. SharedPreferences→DataStore΁ͷҠߦ const val PREFERENCES_NAME = "..." val Context.dataStore by preferencesDataStore(

    name = PREFERENCES_NAME, produceMigrations = { context -> SharedPreferencesMigration( context = context, sharedPreferencesName = PREFERENCES_NAME, // ࢦఆͨ͠keyͷΈҠߦͰ͖ΔʂʢσϑΥϧτҾ਺͸MIGRATE_ALL_KEYSʣ keysToMigrate = setOf(Key.COMIC_USER_IDS) ) } )
  6. ѻ͏σʔλʹ Ԡͯ͡DataStore ͷ࣮૷Λॻ͘ class ComicUserIdsPreferenceImpl @Inject( override val context: Context

    ) : ComicUserIdsPreference { override val userIds: Flow<Set<String>> get() = dataStore.data .catch { if (exception is IOException) { emit(emptyPreferences()) } else { throw exception } } .map { it[PreferencesKeys.ComicUserIds.key] ?: emptySet() } override suspend fun add(id: String) { dataStore.edit { it[PreferencesKeys.ComicUserIds.key] = it[PreferencesKeys.ComicUserIds.key].plus(id).toSet() } } override suspend fun remove(id: String) { dataStore.edit { it[PreferencesKeys.ComicUserIds.key] = it[PreferencesKeys.ComicUserIds.key].minus(id).toSet() } } } Dagger2ͰDIͯ͠·͢ ʢhilitҠߦ͍ͨ͠……ʣ
  7. KeyΛ؅ཧ͢Δ sealed class PreferencesKeys<T>(val key: Preferences.Key<T>) { object ComicUserIds :

    PreferencesKeys<Set<String>>(stringSetPreferencesKey("comic_user_ids")) ... } class PreferenceTest { @Test fun checkDuplicatedKeys() { val subClasses = PreferencesKeys::class.sealedSubclasses val nonDuplicatedKeys = subClasses.map { it.objectInstance?.key?.name }.toSet() Truth.assertThat(nonDuplicatedKeys.count()).isEqualTo(subClasses.count()) } } KeyͷॏෳΛ๷͙ͨΊʹsealed classͰఆٛ ॏෳνΣοΫͷςετ΋͔ͬ͠Γ࣮ࢪ
  8. DataStoreͰಉظॲཧ͢Δ // ςʔϚͷద༻͕׬ྃ͢ΔͷΛ଴ͭͨΊʹrunBlockingͰॲཧ͢Δ runBlocking { initTheme() } private suspend fun

    initTheme() { themeSettingPreference.currentThemeStatus.first().let { AppCompatDelegate.setDefaultNightMode( it.getAppTheme().convertNightModeParameter() ) } }