Bar*_*ine 7 android kotlin dagger-hilt android-jetpack-datastore
我试图提供一个通用的,DataStore<Preferences>以便可以在多个地方使用相同的首选项文件,但我收到了有用的错误消息:
找不到符号:DaggerMyApplication_HiltComponents_SingletonC.builder()
@Module
@InstallIn(ApplicationComponent::class)
object DataStoreModule {
    
    @Provides
    fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences> = context.createDataStore("settings")
}
但是,我可以执行以下操作并在@Inject构造函数中使用它。
@Singleton
class DataStoreProvider @Inject constructor(@ApplicationContext context: Context) {
    val dataStore: DataStore<Preferences> = context.createDataStore("settings")
}
我认为扩展程序createDataStore正在做一些 Hilt 不喜欢的事情,但即使问题无法解决,我也希望能解释一下正在发生的事情。
这对我有用:
    @Provides
    @Singleton
    fun dataStore(@ApplicationContext appContext: Context): DataStore<Preferences> =
        appContext.createDataStore("settings")
这个想法是@Singleton在提供者方法之后。
2021 年 2 月 9 日更新:
最好创建一个经理并提供:
class DataStoreManager(appContext: Context) {
    private val settingsDataStore = appContext.createDataStore("settings")
    suspend fun setThemeMode(mode: Int) {
        settingsDataStore.edit { settings ->
            settings[Settings.NIGHT_MODE] = mode
        }
    }
    val themeMode: Flow<Int> = settingsDataStore.data.map { preferences ->
        preferences[Settings.NIGHT_MODE] ?: AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
    }
}
应用模块:
@InstallIn(SingletonComponent::class)
@Module
class AppModule {
    @Provides
    @Singleton
    fun dataStoreManager(@ApplicationContext appContext: Context): DataStoreManager =
        DataStoreManager(appContext)
2021 年 3 月 20 日更新:
版本 1.0.0-alpha07
private val Context.dataStore by preferencesDataStore("settings")
class DataStoreManager(appContext: Context) {
    private val settingsDataStore = appContext.dataStore
    suspend fun setThemeMode(mode: Int) {
        settingsDataStore.edit { settings ->
            settings[Settings.NIGHT_MODE] = mode
        }
    }
    val themeMode: Flow<Int> = settingsDataStore.data.map { preferences ->
        preferences[Settings.NIGHT_MODE] ?: AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
    }
}
2021 年 5 月 1 日更新: @Florian 是完全正确的,我已经忘记了。
删除dataStoreManager提供程序。然后,
private val Context.dataStore by preferencesDataStore("settings")
@Singleton //You can ignore this annotation as return `datastore` from `preferencesDataStore` is singletone
class DataStoreManager @Inject constructor(@ApplicationContext appContext: Context) {
    private val settingsDataStore = appContext.dataStore
    suspend fun setThemeMode(mode: Int) {
        settingsDataStore.edit { settings ->
            settings[Settings.NIGHT_MODE] = mode
        }
    }
    val themeMode: Flow<Int> = settingsDataStore.data.map { preferences ->
        preferences[Settings.NIGHT_MODE] ?: AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
    }
}
我与 Hilt 一起使用DataStore<Preferences>如下。
持久性模块.kt
@Module
@InstallIn(SingletonComponent::class)
object PersistenceModule {
    @Provides
    @Singleton
    fun provideDataStoreManager(@ApplicationContext context: Context): DataStoreManager {
        return DataStoreManager(context)
    }
}
数据存储管理器.kt
class DataStoreManager @Inject constructor(@ApplicationContext private val context: Context) {
    private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(STORE_NAME)
    private suspend fun <T> DataStore<Preferences>.getFromLocalStorage(
        PreferencesKey: Preferences.Key<T>, func: T.() -> Unit) {
        data.catch {
            if (it is IOException) {
                emit(emptyPreferences())
            } else {
                throw it
            }
        }.map {
            it[PreferencesKey]
        }.collect {
            it?.let { func.invoke(it as T) }
        }
    }
    suspend fun <T> storeValue(key: Preferences.Key<T>, value: T) {
        context.dataStore.edit {
            it[key] = value
        }
    }
    suspend fun <T> readValue(key: Preferences.Key<T>, responseFunc: T.() -> Unit) {
        context.dataStore.getFromLocalStorage(key) {
            responseFunc.invoke(this)
        }
    }
}
ViewModel.kt
@HiltViewModel
class HomeViewModel @Inject constructor(
    private val dataStore: DataStoreManager
) : LiveCoroutinesViewModel() {
    fun readNextReviewTime() {
        viewModelScope.launch {
            dataStore.readValue(nextReviewTime) {
                // Here you can do something with value.
            }
        }
    }
}
更新
@HiltViewModel
class TranslateViewModel @Inject constructor(
    definitionRepository: DefinitionRepository,
    translateRepository: TranslateRepository,
    val dataStoreManager: DataStoreManager
) : LiveCoroutinesViewModel() {
    init {
        readValueInViewModelScope(sourceLanguage, "ta") { // use value here }
        readValueInViewModelScope(targetLanguage, "si") { // use value here }
    }
    private fun <T> readValueInViewModelScope(key: Preferences.Key<T>, defaultValue: T, onCompleted: T.() -> Unit) {
        viewModelScope.launch {
            dataStoreManager.readValue(key) {
                if (this == null) {
                    storeValueInViewModelScope(key, defaultValue)
                } else {
                    onCompleted.invoke(this)
                }
            }
        }
    }
    fun <T> storeValueInViewModelScope(key: Preferences.Key<T>, value: T) {
        viewModelScope.launch {
            dataStoreManager.storeValue(key, value)
        }
    }
}
正如 Dr.jacky 所提到的,现在推荐使用创建管理器的方式,但您仍然可以使用PreferenceDataStoreFactory和创建 Preferences DataStore 单例:
@Provides
@Singleton
fun providePreferencesDataStore(@ApplicationContext appContext: Context): DataStore<Preferences> =
    PreferenceDataStoreFactory.create(
        produceFile = {
            appContext.preferencesDataStoreFile(PREFERENCES_STORE_NAME)
        }
    )
| 归档时间: | 
 | 
| 查看次数: | 1690 次 | 
| 最近记录: |