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
Трудно воспроизвести проблему.