Skip to content

Commit a2020ac

Browse files
committed
Implement temp DataStore class
1 parent 60a021d commit a2020ac

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

firebase-common/firebase-common.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dependencies {
5757

5858
api("com.google.firebase:firebase-components:18.0.0")
5959
api("com.google.firebase:firebase-annotations:16.2.0")
60+
implementation("androidx.datastore:datastore-preferences:1.1.3")
6061
implementation(libs.androidx.annotation)
6162
implementation(libs.androidx.futures)
6263
implementation(libs.kotlin.stdlib)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.google.firebase.datastore
2+
3+
import android.content.Context
4+
import androidx.datastore.core.DataStore
5+
import androidx.datastore.preferences.SharedPreferencesMigration
6+
import androidx.datastore.preferences.core.MutablePreferences
7+
import androidx.datastore.preferences.core.Preferences
8+
import androidx.datastore.preferences.core.edit
9+
import androidx.datastore.preferences.preferencesDataStore
10+
import kotlinx.coroutines.flow.firstOrNull
11+
import kotlinx.coroutines.runBlocking
12+
13+
/**
14+
* Don't use this unless you're bridging Java code Use your own [dataStore] directly in Kotlin code,
15+
* or if you're writing new code.
16+
*/
17+
class DataStorage(val context: Context, val name: String) {
18+
private val transforming = ThreadLocal<Boolean>()
19+
20+
private val Context.dataStore: DataStore<Preferences> by
21+
preferencesDataStore(
22+
name = name,
23+
produceMigrations = { listOf(SharedPreferencesMigration(it, name)) }
24+
)
25+
26+
private val dataStore = context.dataStore
27+
28+
fun <T> getSync(key: Preferences.Key<T>, defaultValue: T): T = runBlocking {
29+
dataStore.data.firstOrNull()?.get(key) ?: defaultValue
30+
}
31+
32+
fun <T> contains(key: Preferences.Key<T>): Boolean = runBlocking {
33+
dataStore.data.firstOrNull()?.contains(key) ?: false
34+
}
35+
36+
fun <T> putSync(key: Preferences.Key<T>, value: T): Preferences = runBlocking {
37+
dataStore.edit { it[key] = value }
38+
}
39+
40+
/** Do not modify the returned map (should be obvious, since it's immutable though) */
41+
fun getAllSync(): Map<Preferences.Key<*>, Any> = runBlocking {
42+
dataStore.data.firstOrNull()?.asMap() ?: emptyMap()
43+
}
44+
45+
/** Edit calls should not be called within edit calls. Is there a way to prevent this? */
46+
fun editSync(transform: (MutablePreferences) -> Unit): Preferences = runBlocking {
47+
if (transforming.get() == true) {
48+
throw IllegalStateException(
49+
"""
50+
Don't call DataStorage.edit() from within an existing edit() callback.
51+
This causes deadlocks, and is generally indicative of a code smell.
52+
Instead, either pass around the initial `MutablePreferences` instance, or don't do everything in a single callback.
53+
"""
54+
.trimIndent()
55+
)
56+
}
57+
transforming.set(true)
58+
try {
59+
dataStore.edit { transform(it) }
60+
} finally {
61+
transforming.set(false)
62+
}
63+
}
64+
}
65+
66+
/** Helper for Java code */
67+
fun <T> Preferences.getOrDefault(key: Preferences.Key<T>, defaultValue: T) =
68+
get(key) ?: defaultValue

0 commit comments

Comments
 (0)