[go: nahoru, domu]

blob: 087a5f866fec4c58e8e0cdc6a4cf4bb39d6acbac [file] [log] [blame]
rohitsat135fe0a262021-02-19 09:28:47 -08001/*
2 * Copyright 2021 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
17package androidx.datastore.preferences.rxjava2
18
19import android.content.Context
20import androidx.annotation.GuardedBy
21import androidx.datastore.core.DataMigration
22import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
23import androidx.datastore.preferences.core.Preferences
24import androidx.datastore.rxjava2.RxDataStore
25import io.reactivex.Scheduler
26import io.reactivex.schedulers.Schedulers
27import kotlin.properties.ReadOnlyProperty
28import kotlin.reflect.KProperty
29
30/**
31 * Creates a property delegate for a single process Preferences DataStore. This should only be
32 * called once
33 * in a file (at the top level), and all usages of the DataStore should use a reference the same
34 * Instance. The receiver type for the property delegate must be an instance of [Context].
35 *
36 * Example usage:
37 * ```
38 * val Context.myRxDataStore by rxPreferencesDataStore("filename", serializer)
39 *
40 * class SomeClass(val context: Context) {
41 * fun update(): Single<Preferences> = context.myRxDataStore.updateDataAsync {...}
42 * }
43 * ```
44 *
45 *
46 * @param name The name of the preferences. The preferences will be stored in a file obtained
47 * by calling: File(context.filesDir, "datastore/" + name + ".preferences_pb")
48 * @param corruptionHandler The corruptionHandler is invoked if DataStore encounters a
49 * [androidx.datastore.core.CorruptionException] when attempting to read data. CorruptionExceptions
50 * are thrown by serializers when data can not be de-serialized.
51 * @param migrations are run before any access to data can occur. Each producer and migration
52 * may be run more than once whether or not it already succeeded (potentially because another
53 * migration failed or a write to disk failed.)
54 * @param scheduler The scope in which IO operations and transform functions will execute.
55 *
56 * @return a property delegate that manages a datastore as a singleton.
57 */
58@JvmOverloads
59public fun rxPreferencesDataStore(
60 name: String,
61 corruptionHandler: ReplaceFileCorruptionHandler<Preferences>? = null,
62 migrations: List<DataMigration<Preferences>> = listOf(),
63 scheduler: Scheduler = Schedulers.io()
64): ReadOnlyProperty<Context, RxDataStore<Preferences>> {
65 return RxDataStoreSingletonDelegate(name, corruptionHandler, migrations, scheduler)
66}
67
68/**
69 * Delegate class to manage DataStore as a singleton.
70 */
71internal class RxDataStoreSingletonDelegate internal constructor(
72 private val fileName: String,
73 private val corruptionHandler: ReplaceFileCorruptionHandler<Preferences>?,
74 private val migrations: List<DataMigration<Preferences>>,
75 private val scheduler: Scheduler
76) : ReadOnlyProperty<Context, RxDataStore<Preferences>> {
77
78 private val lock = Any()
79
80 @GuardedBy("lock")
81 @Volatile
82 private var INSTANCE: RxDataStore<Preferences>? = null
83
84 /**
85 * Gets the instance of the DataStore.
86 *
87 * @param thisRef must be an instance of [Context]
88 * @param property not used
89 */
90 override fun getValue(thisRef: Context, property: KProperty<*>): RxDataStore<Preferences> {
91 return INSTANCE ?: synchronized(lock) {
92 if (INSTANCE == null) {
93 INSTANCE = with(RxPreferenceDataStoreBuilder(thisRef, fileName)) {
94 setIoScheduler(scheduler)
95 migrations.forEach { addDataMigration(it) }
96 corruptionHandler?.let { setCorruptionHandler(it) }
97 build()
98 }
99 }
100 INSTANCE!!
101 }
102 }
103}