5

Android ガイドによると、 Preference Fragments を使用して設定を実装しようとしています。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 をクリックすると得られました

enable_wifi false
enable_wifi false
enable_wifi true
enable_wifi true

そのため、リスナーが複数回呼び出されると思います。それを処理または修正する方法は?

4

3 に答える 3

12

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;
}   

参照用のコールスタックは次のとおりです。

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 
于 2014-08-15T08:30:39.360 に答える