DialogPreference не сохраняет предпочтения, когда я этого ожидаю?

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

1) открыть приложение, и основное действие показывает значение foo из общих настроек по умолчанию = 1

2) зайти в настройки

3) нажмите на настройку foo, которая открывает мой DialogPreference и показывает значение = 1

4) введите значение 3

5) закройте мой DialogPreference с помощью кнопки Ok

***** по умолчанию общие настройки foo теперь должны быть 3

6) нажмите на настройку foo, которая открывает мой DialogPreference и показывает значение = 1

***** Таким образом, моя DialogPreference не сохранила настройки по умолчанию для общих настроек?

7) отменить диалог

8) вернуться к основному виду деятельности, который показывает значение foo из общих настроек по умолчанию = 3

***** так что моя DialogPreference сохранила настройку по умолчанию для общих настроек

9) зайти в настройки

10) нажмите на настройку foo, которая открывает мой DialogPreference и показывает значение 3

Почему на шаге (6) значение общих настроек по умолчанию не равно foo = 3?

Кажется, что предпочтение сохраняется в общих предпочтениях по умолчанию только тогда, когда поток возвращается к основному действию из списка настроек, что противоречит интуитивно понятному сохранению предпочтения в методе onDialogClosed для DialogPreference.

MyDialogPreference

public class MyDialogPreference extends DialogPreference
{
private static final String DEFAULT_VALUE = "0";
private String value = DEFAULT_VALUE;
private EditText editText;

public MyDialogPreference(Context context, AttributeSet attrs)
{
    super(context, attrs);
    setDialogLayoutResource(R.layout.constrained_integer_preference);
}

@Override
public void onBindDialogView(View view)
{
    super.onBindDialogView(view);

    editText = (EditText) view.findViewById(R.id.edit);
    editText.setText("" + value);
}

@Override
protected void onDialogClosed(boolean positiveResult)
{

    if (positiveResult)
    {
        persistString(editText.getText().toString());
    }

    super.onDialogClosed(positiveResult);
}

@Override
protected Object onGetDefaultValue(TypedArray typedArray, int index)
{
    return typedArray.getString(index);
}

@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
{

    if (restorePersistedValue)
    {
        value = getPersistedString(DEFAULT_VALUE);
    }
    else
    {
        value = (String) defaultValue;

        if (shouldPersist())
        {
            persistString(value);
        }

    }

}

}

РЕДАКТИРОВАТЬ: Таким образом, кажется, что предпочтение, которое я обрабатываю с моим DialogPreference, не имеет ключа, который вызывает все проблемы. Но я указал ключ в файле Preferences.xml для этого DialogPreference. Я перепробовал все, чтобы заставить ключ быть распознанным, но ничего не работает.

Может кто-нибудь сказать мне, как я получаю DialogPreference для получения ключа android: из файла preferences.xml для работы?

preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<org.mycompany.myproject.MyDialogPreference
    android:defaultValue="11"
    android:dialogLayout="@layout/my_preference"
    android:inputType="number"
    android:key="MY_KEY"
    android:selectAllOnFocus="true"
    android:singleLine="true"
    android:summary="summary"
    android:title="My Preference" />
</PreferenceScreen>

2 ответа

Решение

В какой-то момент я всегда чувствую, что взламываю Android, и это определенно хак.

Первоначально я думал, что проблема, с которой я боролся, заключалась в том, что инфраструктура игнорирует мой android:key, потому что getKey() возвращает пустую строку, но это не может быть правдой, потому что он получает постоянное значение при запуске PreferenceScreen и сохраняет мои изменения. значения общих настроек, когда я закрываю DialogPreference.

Таким образом, проблема, с которой я борюсь, заключается в том, что платформа считывает постоянные значения предпочтений для внутренних членов, а затем использует внутренние члены, пока поток не выйдет из структуры предпочтений, не обновляя их после закрытия DialogPreference.

Но я наконец-то нашел способ заставить PreferenceScreen обновлять постоянные значения настроек, которые он содержит во внутренних элементах. Хотя это на самом деле не обновление, это взломать.

Так что я в основном выбрасываю PreferenceScreen и создаю новый. Я делаю это, добавляя следующий код в мой метод SettingsFragment.onCreate непосредственно перед addPreferencesFromResource(R.xml.preferences).

    SharedPreferences.OnSharedPreferenceChangeListener prefListener = (prefs, key) ->
    {
        setPreferenceScreen(null);
        addPreferencesFromResource(R.xml.preferences);
    };

    PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()).registerOnSharedPreferenceChangeListener(prefListener);

Это наверное плохо. Я проверял это неоднократно, хотя и не тщательно, и до сих пор не наблюдал каких-либо побочных эффектов.

Так что с этим хаком я теперь могу многократно открывать DialogPreference из PreferenceScreen, сохранять новое значение, а затем возвращаться к DialogPreference с ранее обновленным значением.

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

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

Еще лучше, если кто-то еще может предоставить предпочтительное решение, указав, что я сделал неправильно, вызвавшую проблему, пожалуйста, сделайте это.

РЕДАКТИРОВАТЬ: После того, как работал так долго, этот взлом в конечном итоге сломался, и последовательно.

Но, удаляя взлом, я подошел к проблеме по-новому и, используя тот факт, что я определил, что диалог получает ключ предпочтения, я использовал это исправление для проблемы, которое работает отлично.

Я добавил эту строку кода в начало onBindDialogView

value = getSharedPreferences().getString(getKey(), "-1");

Что делает вызовы onGetDefaultValue и onSetInitialValue избыточными, но они просто не работают, как задумано, по крайней мере, не для меня.

РЕДАКТИРОВАТЬ: Боже мой, я ненавижу это!

Я не заметил, что во время более раннего рефакторинга была удалена строка кода, которая обновляет внутреннее значение DialogPreference в onDialogClosed.

Обычно это что-то простое, и со всем остальным, что я проверял, я пропустил это небольшое изменение.

Я только заметил это во время проверки кода в репозитории, и теперь я чувствую себя глупо. Таким образом, никакого дополнительного кода в конце не потребовалось.

Вам нужно будет реализовать OnPreferenceChangeListener и / или вызвать notifyChanged ().

если вы не предоставите код этого DialogPreferenceТрудно воспроизвести проблему.

Другие вопросы по тегам