Cómo usar valores guardados Parte de Android Jetpack
En este tema, se describe cómo almacenar y usar valores de Preference
guardados en la biblioteca de Preference.
Almacenamiento de datos de Preference
En esta sección, se describe cómo un objeto Preference
puede persistir datos.
SharedPreferences
De forma predeterminada, un objeto Preference
usa SharedPreferences
para guardar valores. La API de SharedPreferences
permite leer y escribir pares clave-valor simples de un archivo que se guarda en las sesiones de la aplicación.
La biblioteca de Preference usa una instancia de SharedPreferences
privada para que solo tu aplicación pueda acceder a ella.
A modo de ejemplo, supongamos el siguiente objeto SwitchPreferenceCompat
:
<SwitchPreferenceCompat app:key="notifications" app:title="Enable message notifications"/>
Cuando un usuario establece este interruptor en el estado On
, se actualiza el archivo SharedPreferences
con un par clave-valor de "notifications" : "true"
. Recuerda que la clave que se usa es la misma que la clave configurada para el objeto Preference
.
Para obtener más información sobre la API de SharedPreferences
, consulta Cómo guardar datos de pares clave-valor.
Para obtener información sobre las formas diferentes de almacenar datos en Android, consulta Descripción general del almacenamiento de datos y archivos.
PreferenceDataStore
Si bien la biblioteca de Preference conserva datos con SharedPreferences
de forma predeterminada, SharedPreferences
no siempre es una solución ideal. Por ejemplo, si tu aplicación requiere que un usuario acceda a su cuenta, se recomienda que conserves la configuración de la aplicación en la nube para que esa configuración se vea reflejada en otros dispositivos y plataformas. De la misma forma, si tu aplicación tiene opciones de configuración que son específicas del dispositivo, cada usuario del dispositivo debería tener configuraciones separadas, de modo que SharedPreferences
deja de ser una solución tan ideal.
Un objeto PreferenceDataStore
te permite usar un backend de almacenamiento personalizado para conservar valores de Preference
. Para obtener más información, consulta Cómo usar un almacén de datos personalizado.
Cómo leer valores de Preference
Para recuperar el objeto SharedPreferences
que se usa, llama a PreferenceManager.getDefaultSharedPreferences()
.
Este método funciona desde cualquier lugar de tu aplicación. Por ejemplo, a partir de un objeto EditTextPreference
con una clave "signature":
<EditTextPreference app:key="signature" app:title="Your signature"/>
El valor guardado para este objeto Preference
se puede recuperar globalmente de la siguiente manera:
Kotlin
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */) val name = sharedPreferences.getString("signature", "")
Java
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */); String name = sharedPreferences.getString(“signature”, "");
Cómo detectar los cambios en los valores de Preference
Para detectar cambios en los valores de Preference
, puedes elegir entre dos interfaces:
La siguiente tabla muestra las diferencias entre las dos interfaces:
OnPreferenceChangeListener | OnSharedPreferenceChangeListener |
---|---|
Se configura para cada elemento Preference. | Se aplica a todos los objetos Preference. |
Se llama cuando un objeto Preference está a punto de cambiar el valor guardado. Esto incluye si el valor pendiente es igual al valor guardado actualmente. | Se llama solamente cuando se modificó el valor guardado de un objeto Preference. |
Solo se llama a través de la biblioteca de Preference. Una parte independiente de la aplicación podría cambiar el valor guardado. | Se llama siempre que se modifica el valor guardado, incluso si se trata de una parte independiente de la aplicación. |
Se llama antes de que se guarde el valor pendiente. | Se llama después de que ya se haya guardado el valor. |
Se llama al usar SharedPreferences o PreferenceDataStore . |
Se llama solamente al usar SharedPreferences . |
OnPreferenceChangeListener
Implementar un objeto OnPreferenceChangeListener
te permite detectar el momento en que el valor de un objeto Preference
está a punto de cambiar. A partir de allí, puedes validar si debería producirse ese cambio. Por ejemplo, el código que se incluye a continuación muestra cómo detectar un cambio en el valor de un objeto EditTextPreference
con una clave "name":
Kotlin
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean { Log.e("preference", "Pending Preference value is: $newValue") return true }
Java
@Override public boolean onPreferenceChange(Preference preference, Object newValue) { Log.e("preference", "Pending Preference value is: " + newValue); return true; }
A continuación, es necesario que configures este objeto de escucha directamente con setOnPreferenceChangeListener()
, tal como se muestra a continuación:
Kotlin
preference.onPreferenceChangeListener = ...
Java
preference.setOnPreferenceChangeListener(...);
OnSharedPreferenceChangeListener
Al crear valores de Preference
persistentes con SharedPreferences
, también puedes usar un objeto SharedPreferences.OnSharedPreferenceChangeListener
para detectar cambios.
De esta forma, puedes detectar en qué momento se cambian los valores guardados por Preference
, por ejemplo, cuando se sincroniza la configuración con un servidor. El siguiente ejemplo muestra cómo detectar el momento en el que cambia el valor de objeto EditTextPreference
con una clave "name":
Kotlin
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { if (key == "signature") { Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, "")) } }
Java
@Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(“signature”)) { Log.i(TAG, “Preference value was updated to: “ + sharedPreferences.getString(key, "")); } }
También debes registrar el objeto de escucha a través de registerOnSharedPreferenceChangedListener()
, como se muestra a continuación:
Kotlin
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)
Java
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);
Kotlin
val listener: SharedPreferences.OnSharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener {...}
Java
SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {...}
Para una administración adecuada del ciclo de vida de tu objeto Activity
o Fragment
, debes registrar y cancelar el registro de este objeto de escucha en las devoluciones de llamada onResume()
y onPause()
, como se muestra a continuación:
Kotlin
override fun onResume() { super.onResume() preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this) } override fun onPause() { super.onPause() preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) }
Java
@Override public void onResume() { super.onResume(); getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); } @Override public void onPause() { super.onPause(); getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); }
Cómo usar un almacén de datos personalizado
Si bien se recomienda crear objetos Preference
persistentes con SharedPreferences
, también puedes usar un almacén de datos personalizado. El almacén de datos personalizado puede ser útil, por ejemplo, si tu aplicación conserva valores en una base de datos o si los valores son específicos del dispositivo.
Cómo implementar el almacén de datos
Para implementar un almacén de datos personalizado, primero debes crear una clase que extienda el objeto PreferenceDataStore
.
El ejemplo de abajo crea un almacén de datos que controla valores de String
:
Kotlin
class DataStore : PreferenceDataStore() { override fun putString(key: String, value: String?) { // Save the value somewhere } override fun getString(key: String, defValue: String?): String? { // Retrieve the value } }
Java
public class DataStore extends PreferenceDataStore { @Override public void putString(String key, @Nullable String value) { // Save the value somewhere } @Override @Nullable public String getString(String key, @Nullable String defValue) { // Retrieve the value } }
No olvides ejecutar cualquier operación que requiera mucho tiempo fuera del subproceso principal para evitar bloquear la interfaz de usuario. Dado que se pueden destruir los objetos Fragment
o Activity
que contienen el almacén de datos mientras conservan un valor, debes serializar los datos para no perder ningún valor que el usuario haya modificado.
Cómo habilitar el almacén de datos
Después de haber implementado tu almacén de datos, debes configurar el nuevo almacén de datos en onCreatePreferences()
para que los objetos Preference
conserven valores con el almacén de datos en vez de usar el objeto SharedPreferences
predeterminado. Se puede habilitar un almacén de datos para cada objeto Preference
o para toda la jerarquía.
A fin de habilitar un almacén de datos personalizado para un objeto Preference
específico, llama a setPreferenceDataStore()
en el objeto Preference
, tal como se muestra en el siguiente ejemplo:
Kotlin
val preference: Preference? = findPreference("key") preference?.preferenceDataStore = dataStore
Java
Preference preference = findPreference(“key”); if (preference != null) { preference.setPreferenceDataStore(dataStore); }
A fin de habilitar un almacén de datos personalizado para una jerarquía entera, llama a setPreferenceDataStore()
en el objeto PreferenceManager
:
Kotlin
val preferenceManager = preferenceManager preferenceManager.preferenceDataStore = dataStore
Java
PreferenceManager preferenceManager = getPreferenceManager(); preferenceManager.setPreferenceDataStore(dataStore);
Si se configura un almacén de datos para un objeto Preference
específico, se anulará cualquier almacén de datos configurado para la jerarquía correspondiente. En la mayoría de los casos, debes configurar un almacén de datos para toda la jerarquía.