Cómo Android SharedPreferences guarda / almacena objetos

217

Necesitamos obtener objetos de usuario en muchos lugares, que contienen muchos campos. Después de iniciar sesión, quiero guardar / almacenar estos objetos de usuario. ¿Cómo podemos implementar este tipo de escenario?

No puedo almacenarlo así:

SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putString("BusinessUnit", strBusinessUnit);
Piraba
fuente
¿Qué tipo de datos quieres almacenar?
ilango j
¿Qué quisiste decir con ~ " y objeto ejecutivo "? Verifique su gramática antes de publicar en StackOverflow.
IgorGanapolsky
Puede usar esta biblioteca que tiene muchas características ... github.com/moinkhan-in/PreferenceSpider
Moinkhan

Respuestas:

549

Puede usar gson.jar para almacenar objetos de clase en SharedPreferences . Puedes descargar este jar de google-gson

O agregue la dependencia GSON en su archivo Gradle:

implementation 'com.google.code.gson:gson:2.8.5'

Crear una preferencia compartida:

SharedPreferences  mPrefs = getPreferences(MODE_PRIVATE);

Ahorrar:

MyObject myObject = new MyObject;
//set variables of 'myObject', etc.

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject);
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

Para recuperar:

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);
Muhammad Aamir Ali
fuente
9
¡Gracias amigo! Pero usted es incorrecto en la parte Guardar (línea 3), el código correcto es: Cadena json = gson.toJson (myObject);
cesarferreira
¿Necesitas los 3 frascos? Hay 3 de ellos en ese enlace. . .
coolcool1994
3
La URL correcta para descargar el jar es: search.maven.org/…
Shajeel Afzal
2
Esto tiene un problema con la referencia circular que conduce a StackOverFlowException xD Lea más aquí stackoverflow.com/questions/10209959/…
phuwin
1
@rozina sí, Gson es mejor. En primer lugar, para usar serializar, el objeto y cada objeto dentro de él deben implementar la interfaz de serialización. Esto no es necesario para gson. gson también funciona muy bien cuando su objeto es una lista de objetos.
Neville Nazerane
36

Para agregar a la respuesta de @ MuhammadAamirALi, puede usar Gson para guardar y recuperar una lista de objetos

Guardar lista de objetos definidos por el usuario en SharedPreferences

public static final String KEY_CONNECTIONS = "KEY_CONNECTIONS";
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();

User entity = new User();
// ... set entity fields

List<Connection> connections = entity.getConnections();
// convert java object to JSON format,
// and returned as JSON formatted string
String connectionsJSONString = new Gson().toJson(connections);
editor.putString(KEY_CONNECTIONS, connectionsJSONString);
editor.commit();

Obtener una lista de objetos definidos por el usuario de SharedPreferences

String connectionsJSONString = getPreferences(MODE_PRIVATE).getString(KEY_CONNECTIONS, null);
Type type = new TypeToken < List < Connection >> () {}.getType();
List < Connection > connections = new Gson().fromJson(connectionsJSONString, type);
toobsco42
fuente
3
¿Qué es "Tipo" allí? (en Obtener lista, segunda línea).
gangadhars
15

Sé que este hilo es un poco viejo. Pero voy a publicar esto de todos modos esperando que pueda ayudar a alguien. Podemos almacenar campos de cualquier objeto a preferencia compartida serializando el objeto a String. Aquí lo he usado GSONpara almacenar cualquier objeto con preferencia compartida.

Guardar objeto en preferencia:

public static void saveObjectToSharedPreference(Context context, String preferenceFileName, String serializedObjectKey, Object object) {
    SharedPreferences sharedPreferences = context.getSharedPreferences(preferenceFileName, 0);
    SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
    final Gson gson = new Gson();
    String serializedObject = gson.toJson(object);
    sharedPreferencesEditor.putString(serializedObjectKey, serializedObject);
    sharedPreferencesEditor.apply();
}

Recuperar objeto de preferencia:

public static <GenericClass> GenericClass getSavedObjectFromPreference(Context context, String preferenceFileName, String preferenceKey, Class<GenericClass> classType) {
    SharedPreferences sharedPreferences = context.getSharedPreferences(preferenceFileName, 0);
    if (sharedPreferences.contains(preferenceKey)) {
        final Gson gson = new Gson();
        return gson.fromJson(sharedPreferences.getString(preferenceKey, ""), classType);
    }
    return null;
}

Nota :

Recuerde agregar compile 'com.google.code.gson:gson:2.6.2'a dependenciessu gradle.

Ejemplo :

//assume SampleClass exists
SampleClass mObject = new SampleObject();

//to store an object
saveObjectToSharedPreference(context, "mPreference", "mObjectKey", mObject);

//to retrive object stored in preference
mObject = getSavedObjectFromPreference(context, "mPreference", "mObjectKey", SampleClass.class);

Actualizar:

Como @Sharp_Edge señaló en los comentarios, la solución anterior no funciona List.

Una ligera modificación a la firma de getSavedObjectFromPreference()- de Class<GenericClass> classTypea Type classTypehará que esta solución se generalice. Firma de función modificada,

public static <GenericClass> GenericClass getSavedObjectFromPreference(Context context, String preferenceFileName, String preferenceKey, Type classType)

Por invocar,

getSavedObjectFromPreference(context, "mPreference", "mObjectKey", (Type) SampleClass.class)

¡Feliz codificación!

tpk
fuente
1
Esto fue realmente útil gracias. Para cualquiera que esté interesado en comentar ... ¿debería llamar a saveObjectToSharedPreference en onSaveInstanceState? Lo tengo en onSaveInstanceState ahora, pero, dado que mi aplicación está recolectando datos en tiempo real cada 10 segundos, tengo problemas de vez en cuando y el objeto que estoy guardando con saveObjectToSharedPreference pierde algunas lecturas. Todos los pensamientos son bienvenidos.
Frank Zappa
Hola @FrankZappa, perdóname porque no entiendo completamente tu problema, pero aquí tienes, intenta usarlo en commitlugar de apply. Te puede ayudar.
tpk
Gracias. Déjame intentar explicar. Mi aplicación de Android recopila datos en tiempo real aproximadamente cada 10 segundos. Esta recopilación de datos no utiliza objetos, solo variables globales y lógica. A continuación, los datos se resumen y almacenan en un objeto Java. Utilizo su método anterior para almacenar y recuperar mi objeto Java en / a través de SharedPreferences porque, a mi entender, no puedo almacenar objetos en onSavedInstanceState yb) cuando la pantalla gira, mi objeto se destruye y se recrea. Por lo tanto, estoy usando su enfoque SharedPrefs, de modo que cuando se gira la pantalla, mi objeto no pierde sus valores. (cont.)
Frank Zappa
Coloqué su rutina saveObjectToSharedPreferences en onSaveInstanceState. Coloqué su rutina getSavedObjectFromPreference en onRestoreInstanceState. Sin embargo, probé y todavía recibí un conjunto de actualizaciones de objetos perdidos debido a la rotación de la pantalla. Por lo tanto, ¿debo mover la llamada a saveObjectToSharedPreferences más cerca de mi lógica real? Por último, ¿a qué método pertenecen commit y apply?
Frank Zappa
1
@ 2943 Su solución se ve muy bien, pero si tengo una lista, por ejemplo, List<CustomClass>¿cómo debo hacer eso? getSavedObjectFromPreference(context, "mPreference", "mObjectKey", SampleClass.class)no acepta List<CustomClass>.class:(
Sharp Edge
6

Mejor es hacer una Constantsclase global para guardar claves o variables para buscar o guardar datos.

Para guardar datos, llame a este método para guardar datos de todas partes.

public static void saveData(Context con, String variable, String data)
{
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(con);
    prefs.edit().putString(variable, data).commit();
}

Úselo para obtener datos.

public static String getData(Context con, String variable, String defaultValue)
{
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(con);
    String data = prefs.getString(variable, defaultValue);
    return data;
}

y un método como este hará el truco

public static User getUserInfo(Context con)
{
    String id =  getData(con, Constants.USER_ID, null);
    String name =  getData(con, Constants.USER_NAME, null);
    if(id != null && name != null)
    {
            User user = new User(); //Hope you will have a user Object.
            user.setId(id);
            user.setName(name);
            //Here set other credentials.
            return user;
    }
    else
    return null;
}
Adil Soomro
fuente
Para recuperar los datos, ¿qué paso como 'variable' y 'defaultValue'?
Alex
Nunca crees una clase de Constantes. Hace que su código esté muy acoplado y disperso al mismo tiempo.
Miha_x64
5

Prueba esta mejor manera:

PreferenceConnector.java

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class PreferenceConnector {
    public static final String PREF_NAME = "ENUMERATOR_PREFERENCES";
    public static final String PREF_NAME_REMEMBER = "ENUMERATOR_REMEMBER";
    public static final int MODE = Context.MODE_PRIVATE;


    public static final String name = "name";


    public static void writeBoolean(Context context, String key, boolean value) {
        getEditor(context).putBoolean(key, value).commit();
    }

    public static boolean readBoolean(Context context, String key,
            boolean defValue) {
        return getPreferences(context).getBoolean(key, defValue);
    }

    public static void writeInteger(Context context, String key, int value) {
        getEditor(context).putInt(key, value).commit();

    }

    public static int readInteger(Context context, String key, int defValue) {
        return getPreferences(context).getInt(key, defValue);
    }

    public static void writeString(Context context, String key, String value) {
        getEditor(context).putString(key, value).commit();

    }

    public static String readString(Context context, String key, String defValue) {
        return getPreferences(context).getString(key, defValue);
    }

    public static void writeLong(Context context, String key, long value) {
        getEditor(context).putLong(key, value).commit();
    }

    public static long readLong(Context context, String key, long defValue) {
        return getPreferences(context).getLong(key, defValue);
    }

    public static SharedPreferences getPreferences(Context context) {
        return context.getSharedPreferences(PREF_NAME, MODE);
    }

    public static Editor getEditor(Context context) {
        return getPreferences(context).edit();
    }

}

Escribe el valor:

PreferenceConnector.writeString(this, PreferenceConnector.name,"Girish");

Y obtenga valor utilizando:

String name= PreferenceConnector.readString(this, PreferenceConnector.name, "");
Patel Girish
fuente
2
¿Qué tiene esto que ver con guardar un objeto en SharedPreferences en Android?
IgorGanapolsky
Puede encontrar más información sobre cómo trabajar con Sharedpreferences en stackoverflow.com/a/2614771/1815624 nota que tal vez quiera usar en return PreferenceManager.getDefaultSharedPreferences(context);lugar dereturn context.getSharedPreferences(PREF_NAME, MODE);
CrandellWS
3

No ha indicado qué hacer con el prefsEditorobjeto después de esto, pero para conservar los datos de preferencia, también debe usar:

prefsEditor.commit();
RivieraKid
fuente
2

Mira aquí, esto puede ayudarte:

public static boolean setObject(Context context, Object o) {
        Field[] fields = o.getClass().getFields();
        SharedPreferences sp = context.getSharedPreferences(o.getClass()
                .getName(), Context.MODE_PRIVATE);
        Editor editor = sp.edit();
        for (int i = 0; i < fields.length; i++) {
            Class<?> type = fields[i].getType();
            if (isSingle(type)) {
                try {
                    final String name = fields[i].getName();
                    if (type == Character.TYPE || type.equals(String.class)) {
                        Object value = fields[i].get(o);
                        if (null != value)
                            editor.putString(name, value.toString());
                    } else if (type.equals(int.class)
                            || type.equals(Short.class))
                        editor.putInt(name, fields[i].getInt(o));
                    else if (type.equals(double.class))
                        editor.putFloat(name, (float) fields[i].getDouble(o));
                    else if (type.equals(float.class))
                        editor.putFloat(name, fields[i].getFloat(o));
                    else if (type.equals(long.class))
                        editor.putLong(name, fields[i].getLong(o));
                    else if (type.equals(Boolean.class))
                        editor.putBoolean(name, fields[i].getBoolean(o));

                } catch (IllegalAccessException e) {
                    LogUtils.e(TAG, e);
                } catch (IllegalArgumentException e) {
                    LogUtils.e(TAG, e);
                }
            } else {
                // FIXME 是对象则不写入
            }
        }

        return editor.commit();
    }

https://github.com/AltasT/PreferenceVObjectFile/blob/master/PreferenceVObjectFile/src/com/altas/lib/PreferenceUtils.java

Altas
fuente
2
¿Podría explicar el código un poco más, ya que actualmente representa "un montón de código"?
Werner
1

Otra forma de guardar y restaurar un objeto desde las preferencias compartidas de Android sin usar el formato Json

private static ExampleObject getObject(Context c,String db_name){
            SharedPreferences sharedPreferences = c.getSharedPreferences(db_name, Context.MODE_PRIVATE);
            ExampleObject o = new ExampleObject();
            Field[] fields = o.getClass().getFields();
            try {
                for (Field field : fields) {
                    Class<?> type = field.getType();
                    try {
                        final String name = field.getName();
                        if (type == Character.TYPE || type.equals(String.class)) {
                            field.set(o,sharedPreferences.getString(name, ""));
                        } else if (type.equals(int.class) || type.equals(Short.class))
                            field.setInt(o,sharedPreferences.getInt(name, 0));
                        else if (type.equals(double.class))
                            field.setDouble(o,sharedPreferences.getFloat(name, 0));
                        else if (type.equals(float.class))
                            field.setFloat(o,sharedPreferences.getFloat(name, 0));
                        else if (type.equals(long.class))
                            field.setLong(o,sharedPreferences.getLong(name, 0));
                        else if (type.equals(Boolean.class))
                            field.setBoolean(o,sharedPreferences.getBoolean(name, false));
                        else if (type.equals(UUID.class))
                            field.set(
                                    o,
                                    UUID.fromString(
                                            sharedPreferences.getString(
                                                    name,
                                                    UUID.nameUUIDFromBytes("".getBytes()).toString()
                                            )
                                    )
                            );

                    } catch (IllegalAccessException e) {
                        Log.e(StaticConfig.app_name, "IllegalAccessException", e);
                    } catch (IllegalArgumentException e) {
                        Log.e(StaticConfig.app_name, "IllegalArgumentException", e);
                    }
                }
            } catch (Exception e) {
                System.out.println("Exception: " + e);
            }
            return o;
        }
        private static void setObject(Context context, Object o, String db_name) {
            Field[] fields = o.getClass().getFields();
            SharedPreferences sp = context.getSharedPreferences(db_name, Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sp.edit();
            for (Field field : fields) {
                Class<?> type = field.getType();
                try {
                    final String name = field.getName();
                    if (type == Character.TYPE || type.equals(String.class)) {
                        Object value = field.get(o);
                        if (value != null)
                            editor.putString(name, value.toString());
                    } else if (type.equals(int.class) || type.equals(Short.class))
                        editor.putInt(name, field.getInt(o));
                    else if (type.equals(double.class))
                        editor.putFloat(name, (float) field.getDouble(o));
                    else if (type.equals(float.class))
                        editor.putFloat(name, field.getFloat(o));
                    else if (type.equals(long.class))
                        editor.putLong(name, field.getLong(o));
                    else if (type.equals(Boolean.class))
                        editor.putBoolean(name, field.getBoolean(o));
                    else if (type.equals(UUID.class))
                        editor.putString(name, field.get(o).toString());

                } catch (IllegalAccessException e) {
                    Log.e(StaticConfig.app_name, "IllegalAccessException", e);
                } catch (IllegalArgumentException e) {
                    Log.e(StaticConfig.app_name, "IllegalArgumentException", e);
                }
            }

            editor.apply();
        }
William Desportes
fuente
1

Puede guardar objetos en preferencias sin usar ninguna biblioteca, antes que nada, su clase de objeto debe implementar Serializable:

public class callModel implements Serializable {

private long pointTime;
private boolean callisConnected;

public callModel(boolean callisConnected,  long pointTime) {
    this.callisConnected = callisConnected;
    this.pointTime = pointTime;
}
public boolean isCallisConnected() {
    return callisConnected;
}
public long getPointTime() {
    return pointTime;
}

}

Luego, puede usar fácilmente estos dos métodos para convertir objetos en cadenas y cadenas en objetos:

 public static <T extends Serializable> T stringToObjectS(String string) {
    byte[] bytes = Base64.decode(string, 0);
    T object = null;
    try {
        ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
        object = (T) objectInputStream.readObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return object;
}

 public static String objectToString(Parcelable object) {
    String encoded = null;
    try {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(object);
        objectOutputStream.close();
        encoded = new String(Base64.encodeToString(byteArrayOutputStream.toByteArray(), 0));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return encoded;
}

Ahorrar:

SharedPreferences  mPrefs = getPreferences(MODE_PRIVATE);
Editor prefsEditor = mPrefs.edit();
prefsEditor.putString("MyObject", objectToString(callModelObject));
prefsEditor.commit();

Leer

String value= mPrefs.getString("MyObject", "");
MyObject obj = stringToObjectS(value);
farhad.kargaran
fuente
Puede evitar la codificación Base64 y el escape de XML simplemente escribiendo estos bytes en un archivo separado.
Miha_x64
1

Paso 1: Copie y pegue estas dos funciones en su archivo java.

 public void setDefaults(String key, String value, Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(key, value);
        editor.commit();
    }


    public static String getDefaults(String key, Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(key, null);
    }

Paso 2: para guardar el uso:

 setDefaults("key","value",this);

para recuperar el uso:

String retrieve= getDefaults("key",this);

Puede establecer diferentes preferencias compartidas utilizando diferentes nombres clave como:

setDefaults("key1","xyz",this);

setDefaults("key2","abc",this);

setDefaults("key3","pqr",this);
Viraj Singh
fuente
1

Si desea almacenar todo el Objeto que obtiene en respuesta, puede lograrlo haciendo algo como,

Primero cree un método que convierta su JSON en una cadena en su clase de utilidad como se muestra a continuación.

 public static <T> T fromJson(String jsonString, Class<T> theClass) {
    return new Gson().fromJson(jsonString, theClass);
}

Luego, en la clase de preferencias compartidas, haga algo como,

 public void storeLoginResponse(yourResponseClass objName) {

    String loginJSON = UtilClass.toJson(customer);
    if (!TextUtils.isEmpty(customerJSON)) {
        editor.putString(AppConst.PREF_CUSTOMER, customerJSON);
        editor.commit();
    }
}

y luego crea un método para getPreferences

public Customer getCustomerDetails() {
    String customerDetail = pref.getString(AppConst.PREF_CUSTOMER, null);
    if (!TextUtils.isEmpty(customerDetail)) {
        return GSONConverter.fromJson(customerDetail, Customer.class);
    } else {
        return new Customer();
    }
}

Luego, simplemente llame al primer método cuando obtenga respuesta y al segundo cuando necesite obtener datos de las preferencias de compartir como

String token = SharedPrefHelper.get().getCustomerDetails().getAccessToken();

eso es todo.

Espero que te ayude.

Happy Coding();

Naresh
fuente
1

Tuve problemas para usar la respuesta aceptada para acceder a los datos de preferencias compartidas en todas las actividades. En estos pasos, le da a getSharedPreferences un nombre para acceder a él.

Agregue la siguiente dependencia en el archivo build.gradel (Módulo: aplicación) en Gradle Scripts:

implementation 'com.google.code.gson:gson:2.8.5'

Ahorrar:

MyObject myObject = new MyObject;
//set variables of 'myObject', etc.

SharedPreferences mPrefs = getSharedPreferences("Name", Context.MODE_PRIVATE);

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject);
prefsEditor.putString("Key", json);
prefsEditor.commit();

Para recuperar en una actividad diferente:

SharedPreferences mPrefs = getSharedPreferences("Name", Context.MODE_PRIVATE);

Gson gson = new Gson();
String json = mPrefs.getString("Key", "");
MyObject obj = gson.fromJson(json, MyObject.class);
Ben
fuente
1
// SharedPrefHelper is a class contains the get and save sharedPrefernce data
public class SharedPrefHelper {

    // save data in sharedPrefences
    public static void setSharedOBJECT(Context context, String key, 
                                           Object value) {

        SharedPreferences sharedPreferences =  context.getSharedPreferences(
                context.getPackageName(), Context.MODE_PRIVATE);

        SharedPreferences.Editor prefsEditor = sharedPreferences.edit();
        Gson gson = new Gson();
        String json = gson.toJson(value);
        prefsEditor.putString(key, json);
        prefsEditor.apply();
    }

    // get data from sharedPrefences 
    public static Object getSharedOBJECT(Context context, String key) {

         SharedPreferences sharedPreferences = context.getSharedPreferences(
                           context.getPackageName(), Context.MODE_PRIVATE);

        Gson gson = new Gson();
        String json = sharedPreferences.getString(key, "");
        Object obj = gson.fromJson(json, Object.class);
        User objData = new Gson().fromJson(obj.toString(), User.class);
        return objData;
    }
}
// save data in your activity

User user = new User("Hussein","[email protected]","3107310890983");        
SharedPrefHelper.setSharedOBJECT(this,"your_key",user);        
User data = (User) SharedPrefHelper.getSharedOBJECT(this,"your_key");

Toast.makeText(this,data.getName()+"\n"+data.getEmail()+"\n"+data.getPhone(),Toast.LENGTH_LONG).show();
// User is the class you want to save its objects

public class User {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    private String name,email,phone;
    public User(String name,String email,String phone){
          this.name=name;
          this.email=email;
          this.phone=phone;
    }
}
// put this in gradle

compile 'com.google.code.gson:gson:2.7'

Espero que esto te ayude :)

usuario7168064
fuente
1

Aquí hay una opinión sobre el uso de las propiedades delegadas de Kotlin que recogí desde aquí , pero que amplié y permite un mecanismo simple para obtener / establecer propiedades SharedPreference.

Para String, Int, Long, Floato Boolean, utiliza el getter estándar SharePreference (s) y setter (s). Sin embargo, para todas las demás clases de datos, utiliza GSON para serializar a a String, para el configurador. Luego se deserializa al objeto de datos, para el captador.

Similar a otras soluciones, esto requiere agregar GSON como dependencia en su archivo gradle:

implementation 'com.google.code.gson:gson:2.8.6'

Aquí hay un ejemplo de una clase de datos simple que nos gustaría poder guardar y almacenar en SharedPreferences:

data class User(val first: String, val last: String)

Aquí está la clase que implementa los delegados de propiedad:

object UserPreferenceProperty : PreferenceProperty<User>(
    key = "USER_OBJECT",
    defaultValue = User(first = "Jane", last = "Doe"),
    clazz = User::class.java)

object NullableUserPreferenceProperty : NullablePreferenceProperty<User?, User>(
    key = "NULLABLE_USER_OBJECT",
    defaultValue = null,
    clazz = User::class.java)

object FirstTimeUser : PreferenceProperty<Boolean>(
        key = "FIRST_TIME_USER",
        defaultValue = false,
        clazz = Boolean::class.java
)

sealed class PreferenceProperty<T : Any>(key: String,
                                         defaultValue: T,
                                         clazz: Class<T>) : NullablePreferenceProperty<T, T>(key, defaultValue, clazz)

@Suppress("UNCHECKED_CAST")
sealed class NullablePreferenceProperty<T : Any?, U : Any>(private val key: String,
                                                           private val defaultValue: T,
                                                           private val clazz: Class<U>) : ReadWriteProperty<Any, T> {

    override fun getValue(thisRef: Any, property: KProperty<*>): T = HandstandApplication.appContext().getPreferences()
            .run {
                when {
                    clazz.isAssignableFrom(String::class.java) -> getString(key, defaultValue as String?) as T
                    clazz.isAssignableFrom(Int::class.java) -> getInt(key, defaultValue as Int) as T
                    clazz.isAssignableFrom(Long::class.java) -> getLong(key, defaultValue as Long) as T
                    clazz.isAssignableFrom(Float::class.java) -> getFloat(key, defaultValue as Float) as T
                    clazz.isAssignableFrom(Boolean::class.java) -> getBoolean(key, defaultValue as Boolean) as T
                    else -> getObject(key, defaultValue, clazz)
                }
            }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = HandstandApplication.appContext().getPreferences()
            .edit()
            .apply {
                when {
                    clazz.isAssignableFrom(String::class.java) -> putString(key, value as String?) as T
                    clazz.isAssignableFrom(Int::class.java) -> putInt(key, value as Int) as T
                    clazz.isAssignableFrom(Long::class.java) -> putLong(key, value as Long) as T
                    clazz.isAssignableFrom(Float::class.java) -> putFloat(key, value as Float) as T
                    clazz.isAssignableFrom(Boolean::class.java) -> putBoolean(key, value as Boolean) as T
                    else -> putObject(key, value)
                }
            }
            .apply()

    private fun Context.getPreferences(): SharedPreferences = getSharedPreferences(APP_PREF_NAME, Context.MODE_PRIVATE)

    private fun <T, U> SharedPreferences.getObject(key: String, defValue: T, clazz: Class<U>): T =
            Gson().fromJson(getString(key, null), clazz) as T ?: defValue

    private fun <T> SharedPreferences.Editor.putObject(key: String, value: T) = putString(key, Gson().toJson(value))

    companion object {
        private const val APP_PREF_NAME = "APP_PREF"
    }
}

Nota: no debería necesitar actualizar nada en el sealed class. Las propiedades son delegadas el inmueble / Singleton UserPreferenceProperty, NullableUserPreferencePropertyy FirstTimeUser.

Para configurar un nuevo objeto de datos para guardar / obtener de SharedPreferences, ahora es tan fácil como agregar cuatro líneas:

object NewPreferenceProperty : PreferenceProperty<String>(
        key = "NEW_PROPERTY",
        defaultValue = "",
        clazz = String::class.java)

Finalmente, puede leer / escribir valores en SharedPreferences simplemente usando la bypalabra clave:

private var user: User by UserPreferenceProperty
private var nullableUser: User? by NullableUserPreferenceProperty
private var isFirstTimeUser: Boolean by 

Log.d("TAG", user) // outputs the `defaultValue` for User the first time
user = User(first = "John", last = "Doe") // saves this User to the Shared Preferences
Log.d("TAG", user) // outputs the newly retrieved User (John Doe) from Shared Preferences
Jason Grife
fuente
0

Si su objeto es complejo, sugeriría serializarlo / XML / JSON y guardar esos contenidos en la tarjeta SD. Puede encontrar información adicional sobre cómo guardar en almacenamiento externo aquí: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal

trenpixster
fuente
¿Eso no requerirá un permiso adicional (tarjeta SD)?
rishabh
Sí, ya que estaría escribiendo en la tarjeta SD.
trenpixster
1
Desde mi experiencia, cuantos menos permisos se requieran para el usuario, mejor. La tarjeta SD debe ser una opción secundaria, si usar Gson como se indicó anteriormente no es una opción viable.
rishabh
Sí, también estoy de acuerdo con eso; Solo si el resultado JSON es lo suficientemente grande, la tarjeta SD debería ser una opción. Es una compensación, diría yo.
trenpixster
0

hay dos archivos resueltos todos sus problemas sobre preferencias compartidas

1) AppPersistence.java

    public class AppPersistence {
    public enum keys {
        USER_NAME, USER_ID, USER_NUMBER, USER_EMAIL, USER_ADDRESS, CITY, USER_IMAGE,
        DOB, MRG_Anniversary, COMPANY, USER_TYPE, support_phone
    }

    private static AppPersistence mAppPersistance;
    private SharedPreferences sharedPreferences;

    public static AppPersistence start(Context context) {
        if (mAppPersistance == null) {
            mAppPersistance = new AppPersistence(context);
        }
        return mAppPersistance;
    }

    private AppPersistence(Context context) {
        sharedPreferences = context.getSharedPreferences(context.getString(R.string.prefrence_file_name),
                Context.MODE_PRIVATE);
    }

    public Object get(Enum key) {
        Map<String, ?> all = sharedPreferences.getAll();
        return all.get(key.toString());
    }

    void save(Enum key, Object val) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        if (val instanceof Integer) {
            editor.putInt(key.toString(), (Integer) val);
        } else if (val instanceof String) {
            editor.putString(key.toString(), String.valueOf(val));
        } else if (val instanceof Float) {
            editor.putFloat(key.toString(), (Float) val);
        } else if (val instanceof Long) {
            editor.putLong(key.toString(), (Long) val);
        } else if (val instanceof Boolean) {
            editor.putBoolean(key.toString(), (Boolean) val);
        }
        editor.apply();
    }

    void remove(Enum key) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.remove(key.toString());
        editor.apply();
    }

    public void removeAll() {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.clear();
        editor.apply();
    }
}

2) AppPreference.java

public static void setPreference(Context context, Enum Name, String Value) {
        AppPersistence.start(context).save(Name, Value);
    }

    public static String getPreference(Context context, Enum Name) {
        return (String) AppPersistence.start(context).get(Name);
    }

    public static void removePreference(Context context, Enum Name) {
        AppPersistence.start(context).remove(Name);
    }
}

ahora puedes guardar, eliminar u obtener,

-salvar

AppPreference.setPreference(context, AppPersistence.keys.USER_ID, userID);

-eliminar

AppPreference.removePreference(context, AppPersistence.keys.USER_ID);

-obtener

 AppPreference.getPreference(context, AppPersistence.keys.USER_ID);
Gautam Surani
fuente
0

Almacenar datos en SharedPreference

SharedPreferences mprefs = getSharedPreferences(AppConstant.PREFS_NAME, MODE_PRIVATE)
mprefs.edit().putString(AppConstant.USER_ID, resUserID).apply();

fuente
0

Mi clase de utilidades para guardar lista en SharedPreferences

public class SharedPrefApi {
    private SharedPreferences sharedPreferences;
    private Gson gson;

    public SharedPrefApi(Context context, Gson gson) {
        this.sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        this.gson = gson;
    } 

    ...

    public <T> void putObject(String key, T value) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(key, gson.toJson(value));
        editor.apply();
    }

    public <T> T getObject(String key, Class<T> clazz) {
        return gson.fromJson(getString(key, null), clazz);
    }
}

Utilizando

// for save
sharedPrefApi.putList(SharedPrefApi.Key.USER_LIST, userList);

// for retrieve
List<User> userList = sharedPrefApi.getList(SharedPrefApi.Key.USER_LIST, User.class);

.
Código completo de mis utilidades // verificar usando el ejemplo en Código de actividad

Phan Van Linh
fuente
0

He usado Jackson para almacenar mis objetos ( Jackson ).

Biblioteca jackson agregada a gradle:

api 'com.fasterxml.jackson.core:jackson-core:2.9.4'
api 'com.fasterxml.jackson.core:jackson-annotations:2.9.4'
api 'com.fasterxml.jackson.core:jackson-databind:2.9.4'

Mi clase de prueba:

public class Car {
    private String color;
    private String type;
    // standard getters setters
}

Objeto Java para JSON:

ObjectMapper objectMapper = new ObjectMapper();
String carAsString = objectMapper.writeValueAsString(car);

Almacénelo en preferencias compartidas:

preferences.edit().car().put(carAsString).apply();

Restaurarlo desde las preferencias compartidas:

ObjectMapper objectMapper = new ObjectMapper();
Car car = objectMapper.readValue(preferences.car().get(), Car.class);
Manuel Schmitzberger
fuente