2009-12-10

[Android] Call PreferenceCategory.addPreference() as earlier as you can

As title of this post says, if you have an Preference to add into a PreferenceCategory, do it as earlier it you can.

I discovered this while fixing a bug of my application. Here is the story,
A Preference of my application that has a hard-coded default value takes the extra data of the Intent object to generate its value and this value will be persisted into SharedPrefereences file when the PreferenceActivity exits.

ListPreference onOffPref = new ListPreference(appContext);
CharSequence[] entries = new CharSequence[]{"On", "Off"};
CharSequence[] entryValues = new CharSequence[]{"true", "false"};
onOffPref.setKey(KEY);
onOffPref.setPersistent(true);
onOffPref.setEntries(entries);
onOffPref.setEntryValues(entryValues);
onOffPref.setDefaultValue("true"); 
onOffPref.setValueIndex(1);

// ..... more processing on getValue();

category.addPreference(onOffPref);

But, as I inspected the preference file in shared_refs/ directory, this Preference always has has its default value persisted. After hours of carefully code review and digging into Android's source code, following lines in PreferenceGroup and Preference caught my sleepy eyes.

// In PreferenceGroup.addPreference(),
preference.onAttachedToHierarchy(getPreferenceManager()); // #156

// In Preference.onAttachedToHierarchy(),
protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
    mPreferenceManager = preferenceManager;

    mId = preferenceManager.getNextId();

    dispatchSetInitialValue(); // <===== Oops, default value!!!
}

See dispatchSetInitialValue()? I am curious that why this PreferenceCategory.addPreference() should "fall back" to use default values. This put a constraint on the use of this method as title says.