Search code examples
androidandroid-fragmentssharedpreferencesandroid-preferencesandroid-settings

PreferenceFragment not saving values - with test case and screenshot


I have prepared a simple test case at GitHub for my question and have a feeling, that only few lines of code are missing to make it working.

In an Android app I have 1 activity (MainActivity.java) and 2 fragments (MainFragment.java and PrefFragment.java) - and when I change values in the preferences fragment, they are not saved.

Also the default values are not loaded and the summaries not updated:

app screenshot

Here is my PrefFragment where I register a shared prefs listener - in order to update the summaries - but for some reason it is never called:

public class PrefFragment extends PreferenceFragment 
    implements OnSharedPreferenceChangeListener {

    public static final String BOOL_1 = "bool_1";
    public static final String STR_1 = "str_1";
    public static final String STR_2 = "str_2";

    private CheckBoxPreference mBool1;
    private EditTextPreference mStr1;
    private EditTextPreference mStr2;
    private SharedPreferences mPrefs;   
    private Editor mEditor;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(false);
        addPreferencesFromResource(R.xml.preferences);
        mBool1 = (CheckBoxPreference) findPreference(BOOL_1);
        mStr1 = (EditTextPreference) findPreference(STR_1);
        mStr2 = (EditTextPreference) findPreference(STR_2);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
        mEditor = mPrefs.edit();
        mPrefs.registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mPrefs.unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences prefs, 
                                          String key) {
        Log.d("onSharedPreferenceChanged", key); // XXX is never called

        if (BOOL_1.equals(key)) {
            boolean bool1 = prefs.getBoolean(key, false);
            mBool1.setSummary(bool1 ? "Enabled" : "Disabled");
        } else if (STR_1.equals(key)) {
            String str1 = prefs.getString(key, "");
            mStr1.setSummary(str1);
        } else if (STR_2.equals(key)) {
            String str2 = prefs.getString(key, "");
            mStr2.setSummary(str2);
        }       
    }    
}

And here is preference.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory 
        android:title="Category 1"
        android:key="category_1">

        <CheckBoxPreference
            android:key="bool_1"
            android:title="Boolean 1"
            android:summary="XXX how to set this? XXX"
            android:defaultValue="false" />
        <EditTextPreference 
            android:dependency="bool_1"
            android:key="str_1"
            android:title="String 1"
            android:summary="XXX how to set this? XXX"
            android:defaultValue="change me" />
        <EditTextPreference 
            android:dependency="bool_1"
            android:key="str_2"
            android:title="String 2"
            android:summary="XXX how to set this? XXX"
            android:defaultValue="change me too" />
        </PreferenceCategory>

</PreferenceScreen>

So my question is how to handle (load, save) values in PreferenceFragment? Do I really have to extend EditTextPreference and implement onDialogClosed method in my custom class? This seems like an overkill approach to me.


Solution

  • Ok, the following seems to work in PrefFragment.java:

    @Override
    public void onResume() {
        super.onResume();
    
        SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
    
        // CHANGE 1: load saved values to set the summaries
        onSharedPreferenceChanged(prefs, BOOL_1);
        onSharedPreferenceChanged(prefs, STR_1);
        onSharedPreferenceChanged(prefs, STR_2);
    
        // CHANGE 2: register shared prefs listener in onResume
        prefs.registerOnSharedPreferenceChangeListener(this);
    }
    
    @Override
    public void onPause() {
        super.onPause();
        SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
        prefs.unregisterOnSharedPreferenceChangeListener(this);
    }