1 /* <lambda>null2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.datastore.rxjava3 18 19 import android.annotation.SuppressLint 20 import android.content.Context 21 import androidx.datastore.core.DataMigration 22 import androidx.datastore.migrations.SharedPreferencesMigration 23 import androidx.datastore.migrations.SharedPreferencesView 24 import io.reactivex.rxjava3.core.Single 25 import kotlinx.coroutines.rx3.await 26 27 @JvmDefaultWithCompatibility 28 /** Client implemented migration interface. */ 29 public interface RxSharedPreferencesMigration<T> { 30 /** 31 * Whether or not the migration should be run. This can be used to skip a read from the 32 * SharedPreferences. 33 * 34 * @param currentData the most recently persisted data 35 * @return a Single indicating whether or not the migration should be run. 36 */ 37 public fun shouldMigrate(currentData: T): Single<Boolean> { 38 return Single.just(true) 39 } 40 41 /** 42 * Maps SharedPreferences into T. Implementations should be idempotent since this may be called 43 * multiple times. See [DataMigration.migrate] for more information. The method accepts a 44 * SharedPreferencesView which is the view of the SharedPreferences to migrate from (limited to 45 * [keysToMigrate]) and a T which represent the current data. The function must return the 46 * migrated data. 47 * 48 * If SharedPreferences is empty or does not contain any keys which you specified, this callback 49 * will not run. 50 * 51 * @param sharedPreferencesView the current state of the SharedPreferences 52 * @param currentData the most recently persisted data 53 * @return a Single of the updated data 54 */ 55 public fun migrate( 56 sharedPreferencesView: SharedPreferencesView, 57 currentData: T 58 ): Single<T & Any> 59 } 60 61 /** RxSharedPreferencesMigrationBuilder for the RxSharedPreferencesMigration. */ 62 @SuppressLint("TopLevelBuilder") 63 public class RxSharedPreferencesMigrationBuilder<T> 64 /** 65 * Construct a RxSharedPreferencesMigrationBuilder. 66 * 67 * @param context the Context used for getting the SharedPreferences. 68 * @param sharedPreferencesName the name of the SharedPreference from which to migrate. 69 * @param rxSharedPreferencesMigration the user implemented migration for this SharedPreference. 70 */ 71 constructor( 72 private val context: Context, 73 private val sharedPreferencesName: String, 74 private val rxSharedPreferencesMigration: RxSharedPreferencesMigration<T> 75 ) { 76 77 private var keysToMigrate: Set<String>? = null 78 79 /** 80 * Set the list of keys to migrate. The keys will be mapped to datastore.Preferences with their 81 * same values. If the key is already present in the new Preferences, the key will not be 82 * migrated again. If the key is not present in the SharedPreferences it will not be migrated. 83 * 84 * This method is optional and if keysToMigrate is not set, all keys will be migrated from the 85 * existing SharedPreferences. 86 * 87 * @param keys the keys to migrate 88 * @return this 89 */ 90 @Suppress("MissingGetterMatchingBuilder") setKeysToMigratenull91 public fun setKeysToMigrate(vararg keys: String): RxSharedPreferencesMigrationBuilder<T> = 92 apply { 93 keysToMigrate = setOf(*keys) 94 } 95 96 /** 97 * Build and return the DataMigration instance. 98 * 99 * @return the DataMigration. 100 */ buildnull101 public fun build(): DataMigration<T> { 102 return if (keysToMigrate == null) { 103 SharedPreferencesMigration( 104 context = context, 105 sharedPreferencesName = sharedPreferencesName, 106 migrate = { spView, curData -> 107 rxSharedPreferencesMigration.migrate(spView, curData).await() 108 }, 109 shouldRunMigration = { curData -> 110 rxSharedPreferencesMigration.shouldMigrate(curData).await() 111 } 112 ) 113 } else { 114 SharedPreferencesMigration( 115 context = context, 116 sharedPreferencesName = sharedPreferencesName, 117 migrate = { spView, curData -> 118 rxSharedPreferencesMigration.migrate(spView, curData).await() 119 }, 120 keysToMigrate = keysToMigrate!!, 121 shouldRunMigration = { curData -> 122 rxSharedPreferencesMigration.shouldMigrate(curData).await() 123 } 124 ) 125 } 126 } 127 } 128