Вызов setDefaultValue() для пользовательского класса Preference не устанавливает значение по умолчанию. Почему?

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

в этом пользовательском параметре (который простирается от ListPreference) я хочу иметь возможность установить значение по умолчанию, поэтому я переопределяю метод setDefaultValue(). В этом методе я выполняю некоторый синтаксический анализ, поэтому он принимает правильное значение. Когда я пытаюсь прочитать это значение с помощью функции getValue(), она просто возвращает null.

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

Любые идеи, что я делаю неправильно?

Редактировать:
Установка значения по умолчанию в XML-файле на самом деле не вариант, потому что значения неизвестны, пока я их не получу.

Я сделал обходной путь:

  • При первом запуске приложения: получить данные
  • Установите значения в настройках.

Таким образом, я устанавливаю предпочтение по умолчанию, когда я собираю данные


person Nick    schedule 03.02.2011    source источник
comment
Вы вызываете setDefaultValue() перед вызовом getValue()? Я установил свои настройки по умолчанию в файле preferences.xml, который читается до создания моего представления предпочтений. Как вы устанавливаете свои настройки по умолчанию?   -  person John J Smith    schedule 03.02.2011
comment
да я делаю, но в коде. Проблема в том, что я не знаю значение по умолчанию, пока приложение не запустится в первый раз. Поэтому я пытаюсь установить его в первый раз, когда пользователь открывает предпочтения.   -  person Nick    schedule 03.02.2011


Ответы (7)


setDefaultValue работает не так, как вы думаете. Посмотрите источник Preference.java, и вы поймете логику всего этого.

Предпочтительный способ установить значение по умолчанию — указать атрибут android:defaultValue в файле preferences.xml вашего приложения.

person Dave    schedule 03.02.2011
comment
Ну, я не могу, потому что записи не статичны. Единственный (грязный) обходной путь, который я вижу, - это просто установить флаг в настройках, которые я установил при установке значения по умолчанию, и просто использовать setValue(). - person Nick; 03.02.2011

Наконец-то я нашел решение (где-то помимо StackOverflow, на этот раз ).

Когда вы создаете собственный класс Preference,

  1. Вам необходимо реализовать onSetInitialValue, как указано XåpplI'-I0llwlg'I -
  2. Вам также необходимо реализовать onGetDefaultValue(TypedArray a, int index)

Например, если пользовательское предпочтение сохранено как int,

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue) {
    setValue(restore ? getPersistedInt(FALLBACK_DEFAULT_VALUE) : (Integer) defaultValue);
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
   return a.getInteger(index, FALLBACK_DEFAULT_VALUE);
}

Теперь PreferenceManager.setDefaultValues() наконец также загружает android:defaultValue для пользовательских настроек. По-прежнему нет исправления для нулей и ложных значений, но есть обходные пути для тех, кто опубликован в другом месте.

person ehartwell    schedule 31.08.2014

Если вы хотите вызвать getValue() после вызова setDefaultValue() для получения значения по умолчанию при первом открытии PreferenceActivity, вам необходимо переопределить onSetInitialValue() в подклассе Preference. В противном случае значение по умолчанию не будет установлено при вызове getValue() и будет возвращено null (как вы уже поняли).

Например, если ваше значение по умолчанию — целое число, ваш onSetInitialValue() может выглядеть так:

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue)
{
    setValue(restore ? getPersistedInt(DEFAULT_VALUE) : (Integer) defaultValue);
}

DEFAULT_VALUE — это просто частная константа внутри Preference, которая будет использоваться в случае, если невозможно получить постоянный int. setValue() — это общедоступный сеттер, дополняющий общедоступный геттер getValue(), и он должен выглядеть примерно так:

public int getValue()
{
    return mValue;
}

public void setValue(int value)
{
    if (value != mValue)
    {
        mValue = value;
        persistInt(value);
    }
}

Дополнительные сведения о onSetInitialValue() см. в документации API здесь.

Также рекомендуется просмотреть исходный код класса Preference (здесь), чтобы понять, почему необходимо реализовать onSetInitialValue(). В частности, посмотрите на setDefaultValue(), а затем посмотрите на dispatchSetInitialValue().

person XåpplI'-I0llwlg'I -    schedule 04.01.2013

Я преобразовал настройки .xml в код. Все setDefaultValue там хорошо работают.

val screen = preferenceManager.createPreferenceScreen(context)

val editText = EditTextPreference(context).apply {
         setIcon(R.drawable.lobat_cloud)
         key = "key"
         title = "MyPreferences"
         ...

         setDefaultValue("My Default Value")
      }

screen.addPreference(editText)

// add other preferences

preferenceScreen = screen

дополнительная информация

P.S: Я нашел этот способ более компактным и понятным, чем настройка всех предпочтений или других ответов.

person beigirad    schedule 29.05.2021

Вы можете расширить предпочтение и установить значение по умолчанию во время построения следующим образом:

package com.example.package.preference;

public class CustomPreference extends ListPreference{

public CustomPreference(Context context) {
    super(context);
    init();
}

public CustomPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    Object anyDefaultValueFromCode = ...
    setDefaultValue(anyDefaultValueFromCode );
}
}

то вы можете использовать его из XML следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="alarm_prefs_screen"
android:title="@string/set_alarm" >

<com.example.package.preference.CustomPreference
    android:key="custom_preference"
    android:title="@string/any_title" />

</PreferenceScreen>
person vir us    schedule 13.06.2013
comment
Кажется, работает только при первом запуске. - person android developer; 16.12.2020

Это то, что я сделал и работал для меня:

class DefaultValueEditTextPreference : androidx.preference.EditTextPreference {
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    @Suppress("unused")
    constructor(context: Context?) : super(context)

    init {
        text = ... //the default, dynamic text that you want to have
    }

}
person android developer    schedule 16.12.2020

Я думаю, что это тоже работает в любое время.

 Preference aaa = (Preference) findPreference("xxx");
 aaa.setOnPreferenceClickListener(new OnPreferenceClickListener() {

              public boolean onPreferenceClick(Preference preference) {

                    // For edit text preference
                    ((EditTextPreference)preference).getEditText().setText("foobar");


                    // for list preference
                    (ListPreference)preference).setValue("foobar");

                    // etc ...

            return true;
              }
 });

Этот код обнаружит, когда диалоговое окно вот-вот запустится, и заполнит EditText или List в диалоговом окне значением по умолчанию.

person Sandstone    schedule 17.12.2011
comment
Это не работает. Значение предпочтения установлено, но, по крайней мере, для ListPreference список не заполняется. - person FabiF; 06.09.2012