android - SwitchPreferences 多次调用 onPreferenceChange() 方法

标签 android android-fragments android-preferences

根据 the Android guide我正在尝试使用首选项 fragment 来实现首选项。在 preferences.xml 中我声明:

<SwitchPreference 
        android:key="enable_wifi"
        android:title="Enable WiFi"
        />

比起在类中,我在 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));
    }
}

因此,当我点击 SwitchPreferene 或 Switch inside log shows 时,我得到了结果

enable_wifi false
enable_wifi false
enable_wifi true
enable_wifi true

这就是为什么我认为监听器被多次调用的原因。如何处理或修复它?

最佳答案

这是由于 SwitchPreference 实现中的错误。

调用回调 onPreferenceChange:

  • 第一次 TwoStatePreference.onClick方法,它只更新 SharedPreference
  • 第二次通过 Switch 小部件的切换状态。 Here它被调用。

无法评论逻辑,但至少框架应该只在状态发生变化时调用 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;
}   

这是供您引用的调用堆栈:

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 

切换小部件切换:

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 

关于android - SwitchPreferences 多次调用 onPreferenceChange() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19503931/

相关文章:

android - 从MySQL获取URL图片并显示在android listView(setImageURI)

android - 无法通过 ?attr 设置标题首选项图标

android - 如何在android首选项中设置日期和时间?

android - 自定义 ListView 适配器 Android

android - 使用 Appium 测试多个 Activity

Android - 什么替代了 NineOldAndroids 动画库?

android - GoogleAnalytics android getActivity().getApplication() 无法转换为 AnalyticsApplication

android - 将接口(interface)传递给 Fragment

android - 当软键盘出现时,Fragment 中的 ScrollView 不滚动

android - 如何将 "long click listener"添加到首选项?