如何对多用户或文件使用 Android DataStore
How to use Android DataStore with multi users or files
我想使用 DataStore 存储一些首选项。但问题是我的应用程序可以有多个用户,因此需要将这些首选项存储在单独的文件中。我得到了一个仅使用一个用户的工作示例,但我正在努力支持多个用户。
这是我的代码示例:
class DataStorageRepository(private val context: Context, private val userRepository: UserRepository) {
private object PreferencesKeys {
val SETTING_ONE = intPreferencesKey("setting_one")
}
// retrieve datastore for currently logged in user.
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = userRepository.currentRegistration().name)
val userPreferencesFlow: Flow<UserPreferences> = context.dataStore.data.map { preferences ->
val settingOne = preferences[PreferencesKeys.SETTING_ONE] ?: 0
UserPreferences(settingOne)
}
suspend fun storeSettingOne(settingOne: Int) {
context.dataStore.edit { preferences ->
preferences[PreferencesKeys.SETTING_ONE] = settingOne
}
}
data class UserPreferences(val lastUsedToAccountTab: Int)
}
我正在使用 Koin
,我尝试在注销时卸载 DataStorageRepository
并在登录时重新创建它,但 DataStore 似乎一直存在,直到应用程序被终止并且出现以下崩溃:
java.lang.IllegalStateException: There are multiple DataStores active
for the same file: [...] You should either maintain your DataStore as
a singleton or confirm that there is no two DataStore's active on the
same file (by confirming that the scope is cancelled).
我还尝试使用 CoroutineScope
并在我注销时将其终止,但在登录时重新创建范围后,似乎没有重新创建数据存储。
DataStore 是否支持关闭连接或处理多个文件的方法?
在我发布这个问题的那一刻,我找到了解决这个问题的方法。为了解决我的问题,我需要结合我之前的两个解决方案。所以在注销时我卸载 DataStorageRepository
并在登录时重新加载它。我还需要创建一个 CoroutineScope
,我在注销时取消它。
我的模块
val loggedInModule = module {
single { DataStorageRepository(get(), get()) }
}
我创建了一个范围并将其传递给 DataStore
var loggedInScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = userRepository.currentRegistration().name, scope = loggedInScope)
登录时
loggedInScope = CoroutineScope(Dispatchers.Default)
loadKoinModules(loggedInModule)
注销时
loggedInScope.cancel()
unloadKoinModules(loggedInModule)
您可以为不同的用户使用不同的密钥或手动保留 DataStore 单例。
例外情况:
java.lang.IllegalStateException: There are multiple DataStores active for the same file: [...] You should either maintain your DataStore as a singleton or confirm that there is no two DataStore's active on the same file (by confirming that the scope is cancelled).
androidx.datastore:datastore-*:1.0.0-alpha07
已发布。
将它放在你的 kotlin 文件的顶层,这样它只有一个实例。
private val Context.dataStore by preferencesDataStore("settings")
class Xxx{
}
https://developer.android.com/jetpack/androidx/releases/datastore#1.0.0-alpha07.
The Context.createDataStore extension function has been removed and replaced with globalDataStore property delegate. Call globalDataStore once at the top level in your kotlin file. For example:
val Context.myDataStore by dataStore(...)
Put this at the top level of your kotlin file so there is only one instance of it. (I57215, b/173726702)
将此行放入伴随对象 { }
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settingPrefs")
我的代码
class SettingPrefs(private val context: Context) {
companion object {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settingPrefs")
private val soundKey = booleanPreferencesKey("sound")
private val vibrateKey = booleanPreferencesKey("vibrate")
}
val getSound: Flow<Boolean>
get() = context.dataStore.data.map {
it[soundKey] ?: true
}
suspend fun setSound(value: Boolean) {
context.dataStore.edit { it[soundKey] = value }
}
val getVibration: Flow<Boolean>
get() = context.dataStore.data.map {
it[vibrateKey] ?: true
}
suspend fun setVibration(value: Boolean) {
context.dataStore.edit { it[vibrateKey] = value }
}
}
只需将声明数据存储从 DataStorageRepository 中取出即可 class
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name="settings")
class DataStorageRepository(context: Context) {
private var appContext = context.applicationContext
val mData: Flow<String?> = appContext.dataStore.data.map { preferences ->
preferences[YOUR_KEY]
}
suspend fun insertData(value: String) {
appContext.dataStore.edit { preferences ->
preferences[YOUR_KEY] = authToken
}
}
companion object {
private val KEY = stringPreferencesKey("data")
}
}
我想使用 DataStore 存储一些首选项。但问题是我的应用程序可以有多个用户,因此需要将这些首选项存储在单独的文件中。我得到了一个仅使用一个用户的工作示例,但我正在努力支持多个用户。
这是我的代码示例:
class DataStorageRepository(private val context: Context, private val userRepository: UserRepository) {
private object PreferencesKeys {
val SETTING_ONE = intPreferencesKey("setting_one")
}
// retrieve datastore for currently logged in user.
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = userRepository.currentRegistration().name)
val userPreferencesFlow: Flow<UserPreferences> = context.dataStore.data.map { preferences ->
val settingOne = preferences[PreferencesKeys.SETTING_ONE] ?: 0
UserPreferences(settingOne)
}
suspend fun storeSettingOne(settingOne: Int) {
context.dataStore.edit { preferences ->
preferences[PreferencesKeys.SETTING_ONE] = settingOne
}
}
data class UserPreferences(val lastUsedToAccountTab: Int)
}
我正在使用 Koin
,我尝试在注销时卸载 DataStorageRepository
并在登录时重新创建它,但 DataStore 似乎一直存在,直到应用程序被终止并且出现以下崩溃:
java.lang.IllegalStateException: There are multiple DataStores active for the same file: [...] You should either maintain your DataStore as a singleton or confirm that there is no two DataStore's active on the same file (by confirming that the scope is cancelled).
我还尝试使用 CoroutineScope
并在我注销时将其终止,但在登录时重新创建范围后,似乎没有重新创建数据存储。
DataStore 是否支持关闭连接或处理多个文件的方法?
在我发布这个问题的那一刻,我找到了解决这个问题的方法。为了解决我的问题,我需要结合我之前的两个解决方案。所以在注销时我卸载 DataStorageRepository
并在登录时重新加载它。我还需要创建一个 CoroutineScope
,我在注销时取消它。
我的模块
val loggedInModule = module {
single { DataStorageRepository(get(), get()) }
}
我创建了一个范围并将其传递给 DataStore
var loggedInScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = userRepository.currentRegistration().name, scope = loggedInScope)
登录时
loggedInScope = CoroutineScope(Dispatchers.Default)
loadKoinModules(loggedInModule)
注销时
loggedInScope.cancel()
unloadKoinModules(loggedInModule)
您可以为不同的用户使用不同的密钥或手动保留 DataStore 单例。
例外情况:
java.lang.IllegalStateException: There are multiple DataStores active for the same file: [...] You should either maintain your DataStore as a singleton or confirm that there is no two DataStore's active on the same file (by confirming that the scope is cancelled).
androidx.datastore:datastore-*:1.0.0-alpha07
已发布。
将它放在你的 kotlin 文件的顶层,这样它只有一个实例。
private val Context.dataStore by preferencesDataStore("settings")
class Xxx{
}
https://developer.android.com/jetpack/androidx/releases/datastore#1.0.0-alpha07.
The Context.createDataStore extension function has been removed and replaced with globalDataStore property delegate. Call globalDataStore once at the top level in your kotlin file. For example:
val Context.myDataStore by dataStore(...)
Put this at the top level of your kotlin file so there is only one instance of it. (I57215, b/173726702)
将此行放入伴随对象 { }
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settingPrefs")
我的代码
class SettingPrefs(private val context: Context) {
companion object {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settingPrefs")
private val soundKey = booleanPreferencesKey("sound")
private val vibrateKey = booleanPreferencesKey("vibrate")
}
val getSound: Flow<Boolean>
get() = context.dataStore.data.map {
it[soundKey] ?: true
}
suspend fun setSound(value: Boolean) {
context.dataStore.edit { it[soundKey] = value }
}
val getVibration: Flow<Boolean>
get() = context.dataStore.data.map {
it[vibrateKey] ?: true
}
suspend fun setVibration(value: Boolean) {
context.dataStore.edit { it[vibrateKey] = value }
}
}
只需将声明数据存储从 DataStorageRepository 中取出即可 class
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name="settings")
class DataStorageRepository(context: Context) {
private var appContext = context.applicationContext
val mData: Flow<String?> = appContext.dataStore.data.map { preferences ->
preferences[YOUR_KEY]
}
suspend fun insertData(value: String) {
appContext.dataStore.edit { preferences ->
preferences[YOUR_KEY] = authToken
}
}
companion object {
private val KEY = stringPreferencesKey("data")
}
}