DropDownPreference setOnPreferenceChangeListener calls itself when initialized

谁都会走 提交于 2020-06-17 09:46:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!