Llamar a SetDefaultValue () en una clase de preferencia personalizada no establece el valor predeterminado. ¿Por qué?

StackOverflow https://stackoverflow.com/questions/4886469

Pregunta

Estoy extendiendo PreferenceActivity para mi pantalla de configuración. En esta actividad de preferencia tengo un par de preferencias, una de las cuales está hecha a medida. El problema es el siguiente:

En esta preferencia personalizada (que se extiende desde ListPreference) Quiero poder establecer el valor predeterminado, por lo que anulé el setDefaultValue() método. En este método hago un análisis para que tome el valor correcto. Cuando intento leer este valor con el getValue() función simplemente regresa null.

Así que pensé, lo que sucede cuando solo ponía un valor codificado allí (ya sabes, tal vez hice algo mal, no sería la primera vez). Bueno, sigo siendo null espalda.

¿Alguna idea de lo que estoy haciendo mal?

Editar:
Configurar el valor predeterminado en el archivo XML no es realmente una opción porque los valores no se conocen hasta que los recupere.

Hice una solución:

  • Cuando la aplicación se inicia por primera vez: Obtenga datos
  • Establezca los valores en la preferencia.

De esta manera, establecí la preferencia predeterminada cuando recopile los datos

¿Fue útil?

Solución

setDefaultValue No funciona de la manera que crees que lo hace. Mirar la fuente de Preference.java y la lógica detrás de todo.

La forma preferida de establecer un valor predeterminado es especificar el android:defaultValue atributo en el preferences.xml archivo de su aplicación.

Otros consejos

Finalmente encontré la solución (en algún lugar además de Stackoverflow, por una vez).

Cuando crea una clase de preferencia personalizada,

  1. Necesitas implementar onSetInitialValue como Xåppli' -i0llwlg'i - señalado
  2. además necesidad de implementar onGetDefaultValue(TypedArray a, int index)

Por ejemplo, si la preferencia personalizada se guarda como 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);
}

Ahora PreferenceManager.setDefaultValues() finalmente carga el android:defaultValue para las preferencias personalizadas también. Todavía no hay solución para nulos y falsos, pero hay soluciones para los publicados en otros lugares.

Si quieres llamar getValue() después de llamar setDefaultValue() Para recuperar un valor predeterminado la primera vez que se abre su reactividad de preferencias, debe anular onSetInitialValue() en su subclase de preferencia. De lo contrario, el valor predeterminado no se establecerá cuando llame getValue() y devolverá un null (como experimentó).

Por ejemplo, si su valor predeterminado es un entero, su onSetInitialValue() podría verse así:

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

DEFAULT_VALUE es solo una constante privada dentro de la preferencia que se utilizará en caso de que el INT persistido no se pueda recuperar. setValue() es el setter público para complementar su getValue() Getter público, y debería verse algo así:

public int getValue()
{
    return mValue;
}

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

Para más información sobre onSetInitialValue(), consulte la documentación de la API aquí.

También es una buena idea ver el código fuente de la clase de preferencia (aquí) para entender por qué onSetInitialValue() necesita ser implementado. En particular, eche un vistazo a setDefaultValue(), y luego mira dispatchSetInitialValue().

Puede extender la preferencia y establecer el valor predeterminado durante la construcción de esta manera:

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 );
}
}

Entonces puedes usarlo desde XML como este:

<?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>

Creo que esto también funciona en cualquier momento.

 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;
              }
 });

Este código detectará cuándo el cuadro de diálogo está a punto de iniciarse y pueblando el editText o la lista en el cuadro de diálogo con su valor predeterminado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top