It is due to the bug in SwitchPreference
implementation.
The callback onPreferenceChange
is called:
- First time by TwoStatePreference.onClick method, which just updates the
SharedPreference
.
- Second time by the toggle state of the
Switch
widget. Here it is invoked.
Can't comment on the logic, but atleast the framework should have taken care of invoking onPreferenceChange
callback only if there was a change in the state. So the responsibility lies with us. Use SwitchPreference.isChecked method to check whether the state got changed.
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(((SwitchPreference) preference).isChecked() != (Boolean) newValue) {
// State got changed
Log.i("Testing", preference.getKey() + " : " + String.valueOf(newValue));
// If you don't want to save the preference change return false from this if block.
}
return true;
}
Here is the callstack for your reference:
TwoStatePreference.onClick :
MainActivity$SettingsFragment$1.onPreferenceChange(Preference, Object) line: 45
SwitchPreference(Preference).callChangeListener(Object) line: 895
SwitchPreference(TwoStatePreference).onClick() line: 65
SwitchPreference(Preference).performClick(PreferenceScreen) line: 950
PreferenceScreen.onItemClick(AdapterView, View, int, long) line: 215
ListView(AdapterView).performItemClick(View, int, long) line: 298
ListView(AbsListView).performItemClick(View, int, long) line: 1100
AbsListView$PerformClick.run() line: 2788
AbsListView$1.run() line: 3463
Handler.handleCallback(Message) line: 730
ViewRootImpl$ViewRootHandler(Handler).dispatchMessage(Message) line: 92
Looper.loop() line: 137
Switch widget toggle :
MainActivity$SettingsFragment$1.onPreferenceChange(Preference, Object) line: 45
SwitchPreference(Preference).callChangeListener(Object) line: 895
SwitchPreference$Listener.onCheckedChanged(CompoundButton, boolean) line: 47
Switch(CompoundButton).setChecked(boolean) line: 126
Switch.setChecked(boolean) line: 666
SwitchPreference.onBindView(View) line: 106