SwitchPreferences多次调用onPreferenceChange()方法

gho*_*ost 5 android android-preferences android-fragments

根据Android指南,我正在尝试使用Preference Fragments实现首选项.在preferences.xml我声明:

<SwitchPreference 
        android:key="enable_wifi"
        android:title="Enable WiFi"
        />
Run Code Online (Sandbox Code Playgroud)

而且在课堂上thah在onCreate方法中扩展了PreferenceFragment,我做了:

public class FragmentSettings extends PreferenceFragment {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    addPreferencesFromResource(R.xml.preferences);

    mEnableWifi = (SwitchPreference) findPreference(enable_wifi);
    mEnableWiFi.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {

        Log.i(getClass().getName(), preference.getKey()
            + String.valueOf(newValue));
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当我登录SwitchPreferene或Switch内部日志显示时,我得到了

enable_wifi false
enable_wifi false
enable_wifi true
enable_wifi true
Run Code Online (Sandbox Code Playgroud)

所以这就是为什么我认为监听器被多次调用.如何处理或修复它?

Man*_*ani 11

这是由于SwitchPreference实施中的错误.

回调onPreferenceChange被称为:

无法评论逻辑,但至少onPreferenceChange只有在状态发生变化时,框架才应该注意调用回调.所以责任在于我们.使用SwitchPreference.isChecked方法检查状态是否已更改.

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;
}   
Run Code Online (Sandbox Code Playgroud)

这是callstack供您参考:

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 
Run Code Online (Sandbox Code Playgroud)

切换小部件切换:

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 
Run Code Online (Sandbox Code Playgroud)


Sim*_*mas 1

奇怪的是,OP 的代码缺少 的 return 语句onPreferenceChange

确保您return true;在最后调用,以便确实更改首选项。

但是,如果问题仍然存在,请在首选项更改侦听器内部进行检查,以便它不会进行不必要的更新:

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    if (preference.isEnabled() != newValue) {
        // Do something on normal switch
        return true;
    } else {
        // Preference wasn't changed, do nothing and don't update it
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)