GetPreferences всегда возвращает значение по умолчанию

Я установил PreferenceFragment с двумя булевыми настройками. Fragment работает отлично, и настройки сохраняются, когда приложение закрыто и повторно открыто. Однако у меня возникают проблемы при попытке прочитать эти ценности; возвращается только значение по умолчанию. Если я отлаживаю метод getBoolean SharedPreferences, я вижу, что локальный HashMap имеет размер 0, поэтому возвращается значение по умолчанию, например:

public boolean getBoolean(String key, boolean defValue) {
    synchronized (this) {
        awaitLoadedLocked();
        Boolean v = (Boolean)mMap.get(key); // <-- mMap is of size 0: return defValue
        return v != null ? v : defValue;
    }
}

Я нахожу это странным, поскольку значения предпочтений, очевидно, хранятся и загружаются должным образом в PreferenceFragment. Что мне не хватает?

В Activity.onCreate():

PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

Рез /XML/preferences.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:key="mm_preferences_category_recipe_preferences"
        android:title="@string/mm_preferences_category_recipe_preferences_title" >
        <CheckBoxPreference
            android:key="@string/mm_preferences_numbers_as_fractions_key"
            android:title="@string/mm_preferences_numbers_as_fractions_title"
            android:summary="@string/mm_preferences_numbers_as_fractions_summary"
            android:defaultValue="true" />
        <CheckBoxPreference
            android:key="@string/mm_preferences_comma_as_decimal_separator_key"
            android:title="@string/mm_preferences_comma_as_decimal_separator_title"
            android:summary="@string/mm_preferences_comma_as_decimal_separator_summary"
            android:defaultValue="true" />
    </PreferenceCategory>
</PreferenceScreen>

Мой PreferenceFragment класс:

public class MiasMatPreferencesFragment extends PreferenceFragment
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }
}

Теперь, делая это в любом месте приложения, возвращает только значения по умолчанию (true в обоих случаях), хотя PreferenceFragment показывает, что значения установлены на false (если это так):

boolean foo = getPreferences(Context.MODE_PRIVATE).getBoolean(getString(R.string.mm_preferences_numbers_as_fractions_key), true);
boolean bar = getPreferences(Context.MODE_PRIVATE).getBoolean(getString(R.string.mm_preferences_comma_as_decimal_separator_key), true);

Ответ 1

После того, как я занялся этим несколько часов, я понял, почему это не сработало для меня. В одном приложении есть несколько SharedPreferences, которые я не понял. Это означает, что (1) Activity.getPreferences(int mode), (2) Context.getSharedPreferences(String name, int mode) и (3) PreferenceManager.getDefaultSharedPreferences(Context context) возвращает разные экземпляры SharedPreferences.

В моем случае решение заключалось в использовании PreferenceManager.getDefaultSharedPreferences(Context context). Это связано с тем, что я использую пользовательскую библиотеку для обратной совместимости PreferenceFragment. Эта библиотека записывает файл настроек по умолчанию.

Из документов:

PreferenceManager.getDefaultSharedPreferences(Context context)

Получает экземпляр SharedPreferences, который указывает на файл по умолчанию, используемый структурой предпочтений в данном контексте.

Итак, это предпочтения для данного Context или Activity в любое время с использованием имени файла по умолчанию для настроек. Это статический экземпляр класса PreferenceManager.

Context.getSharedPreferences(String name, int mode)

Получить и сохранить содержимое файла настроек "имя", возвращая SharedPreferences, через который вы можете получить и изменить свои значения. Только один экземпляр объекта SharedPreferences возвращается всем вызывающим абонентам с тем же именем, то есть они будут видеть изменения друг друга, как только они будут сделаны.

Используя этот метод, вы можете различать несколько файлов предпочтений, используя аргумент String.

Activity.getPreferences(int mode)

Получить объект SharedPreferences для доступа к предпочтениям, которые являются приватными для этого действия.

Этот метод вызывает прямое предыдущее: getSharedPreferences(getLocalClassName(), mode). Следовательно, он указывает на файл в зависимости от имени Activity.

Другие связанные вопросы (возможные дубликаты):

Разница между getDefaultSharedPreferences и getSharedPreferences

PreferenceManager.getDefaultSharedPreferences() vs getPreferences()