如何解决从 Preferences DataStore 读取返回 null
即使我使用 elvis 运算符在首选项管理器上设置了默认值,我的 DataStore 也一直返回 null。此外,我在键值对上设置首选项的编辑功能没有被调用,所以我什至不确定我的数据存储是否正确设置。不过,我很确定该类已正确注入,因为我可以在使用断点时将其视为变量。
基本上在 viewmodel 上的 val countryCode = viewmodel.countrySettings.value
总是返回 null
PreferencesManager 类
const val TAG = "PreferencesManager"
const val DEFAULT_COUNTRY_PREFERENCE = "us"
const val DEFAULT_CATEGORY_PREFERENCE = "general"
private val Context.dataStore by preferencesDataStore(name = PREFERENCES_NAME)
@Singleton
class PreferencesManager @Inject constructor(@ApplicationContext appContext: Context) {
private val preferencesDataStore = appContext.dataStore
//Pairs are separated but I'll create an appropriate data class later.
val countrySettings = preferencesDataStore.data
.catch { exception ->
if (exception is IOException) {
Log.e(TAG,"Error while trying to read user preferences",exception)
emit(emptyPreferences())
} else {
throw exception
}
}
.map { preference ->
val country = preference[PreferenceKeys.COUNTRY] ?: DEFAULT_COUNTRY_PREFERENCE
country
}
val categorySettings = preferencesDataStore.data
.catch { exception ->
if (exception is IOException) {
Log.e(TAG,exception)
emit(emptyPreferences())
} else {
throw exception
}
}
.map { preferences ->
val category = preferences[PreferenceKeys.CATEGORY] ?: DEFAULT_CATEGORY_PREFERENCE
category
}
suspend fun setCountryPreference(country: String) {
preferencesDataStore.edit { preference ->
preference[PreferenceKeys.COUNTRY] = country
}
}
suspend fun setCategoryPreference(category: String) {
preferencesDataStore.edit { preference ->
preference[PreferenceKeys.CATEGORY] = category
}
}
private object PreferenceKeys {
val COUNTRY = stringPreferencesKey("country")
val CATEGORY = stringPreferencesKey("category")
}
}
视图模型
class Mainviewmodel @Inject constructor(
private val repository: Repository,private val preferencesManager: PreferencesManager
): viewmodel() {
val countrySettings = preferencesManager.countrySettings.asLiveData()
val categorySettings = preferencesManager.categorySettings.asLiveData()
/* .... */
fun setCountryPreference(country: String) {
viewmodelScope.launch {
preferencesManager.setCountryPreference(country)
}
}
fun setCategoryPreference(category: String) {
viewmodelScope.launch {
preferencesManager.setCategoryPreference(category)
}
}
}
片段
val viewmodel: Mainviewmodel by activityviewmodels()
private var _binding: FragmentSettingsCountryScreenBinding? = null
private val binding get() = _binding!!
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
_binding = FragmentSettingsCountryScreenBinding.bind(view)
//Using breakpoints I've noticed this function isn't even called on the preferences manager to set the value,which is weird
viewmodel.setCountryPreference("us")
val countryCode = viewmodel.countrySettings.value
binding.radiogroup.check(adaptPreferenceFromDataStore(countryCode!!))
binding.radiogroup.setonCheckedchangelistener { _,checkedId ->
viewmodel.setCountryPreference(adaptPreferencetoDataStore(checkedId))
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
解决方法
是的,ianhanniballake 是正确的,这是一个新手错误 - 我完全忘记了我必须观察 livedata 值然后才设置 UI 参数。我试图根据几个开关的值设置首选项(反之亦然)。这是设置它的正确功能:
fun setupSwitches() {
viewModel.countrySettings.observe(viewLifecycleOwner,{ preference ->
binding.radioGroup.check(adaptPreferenceFromDataStore(preference))
})
binding.radioGroup.setOnCheckedChangeListener { _,checkedId ->
viewModel.setCountryPreference(adaptPreferenceToDataStore(checkedId))
}
}
然后在 setupSwitches()
上调用了 onViewCreated
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。