问题
I have filed a bug here on this issue which I believe is a platform bug. If you have a DropDownPreference OnPreferenceChangeListener, Android appears to "choose" the first item once and only once when the screen is first opened on a fresh app, thereby firing the listener.
Has anyone seen this behavior and how might I prevent it? I tried putting in a boolean preference flag to filter the misfire out, but now the first option in my dropdown is unselectable until I choose another option. I believe behind the scenes, the PreferenceFragmentCompat
thinks the first option in the dropdown is the "default", and I have tried using setDefaultValue
and setValueIndex
on the preference to try and initialize it programmatically to no avail. The xml preference has no default value set.
My dropdown preference is called "prep time", and it's initial value comes from our server and then from a local db:
val setting = settings.getSettingByName(preferencesHelper.merchantBranchID, AppConstants.Settings.PREP_TIME)
if (setting != null) {
var prepTime = setting.value
if (prepTime.isEmpty()) {
prepTime = "15"
}
val summaryProvider = Preference.SummaryProvider<DropDownPreference> {
if (prepTime.toInt() == 1)
"$prepTime minute"
else
"$prepTime minutes"
}
val preference = findPreference<DropDownPreference>(AppConstants.Settings.PREP_TIME)
withContext(Dispatchers.Main) {
preference?.summaryProvider = summaryProvider
preference?.setDefaultValue(setting.value)
}
preference?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { pref, newValue ->
if(prefs.prepTimePreferenceInittedDueToPlatformBug) {
updateSetting(groupID, branchID, setting.id, newValue.toString())
.observe(viewLifecycleOwner, Observer { response ->
response?.let {
Timber.i("Settings put observed, status= " + response.status + ", data=" + response.data)
})
prepTime = newValue.toString()
}
else{
//We need to do this to prevent a false positive for new installs.
//Dropdown preferences exhibit this, which I think is a platform bug, reported:
//https://issuetracker.google.com/issues/156047817
prefs.prepTimePreferenceInittedDueToPlatformBug = true
}
true
}
}
回答1:
As far as I can tell this is related to Spinners. Something triggers it when it shouldn't, and if it is this bug then it will not be fixed. There are many ridiculous hacks to this one. Here is my solution extended from one of the answers there:
var actualSpinnerClick = false;
preference?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
actualSpinnerClick = true
true
}
preference?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { pref, newValue ->
if(actualSpinnerClick) {
actualSpinnerClick = false;
updateSetting(groupID, branchID, setting.id, newValue.toString())
.observe(viewLifecycleOwner, Observer { response ->
response?.let {
Timber.i("Settings put observed, status= " + response.status + ", data=" + response.data)
}
})
prepTime = newValue.toString()
}
true
}
来源:https://stackoverflow.com/questions/61867118/dropdownpreference-setonpreferencechangelistener-calls-itself-when-initialized