almacenar y recuperar un objeto de clase en preferencia compartida


111

En Android, ¿podemos almacenar un objeto de una clase en preferencia compartida y recuperar el objeto más tarde?

Si es posible, ¿cómo hacerlo? Si no es posible, ¿cuáles son las otras posibilidades de hacerlo?

Sé que la serialización es una opción, pero estoy buscando posibilidades usando preferencias compartidas.


Agrego una biblioteca auxiliar en caso de que alguien la necesite: github.com/ionull/objectify
Tsung Goh


Aquí hay una respuesta a una pregunta similar.
tpk


Puede usar esta biblioteca que tiene muchas características incorporadas. github.com/moinkhan-in/PreferenceSpider
Moinkhan

Respuestas:


15

Imposible.

Solo puede almacenar valores simples en SharedPrefences SharePreferences.Editor

¿Qué hay en particular de la clase que necesitas guardar?


1
Gracias. Quiero almacenar algunos miembros de datos de la clase. Y no quiero almacenar cada valor de los miembros de datos usando preferencia compartida. Quiero almacenarlo como un objeto. Si no tengo preferencia compartida, ¿cuáles son mis otras opciones?
androidGuy

5
Serializarlo y almacenarlo, en una base de datos (SQLite) / en un archivo plano.
Blundell

5
La respuesta no es completa. La posible solución es transformar el pojo en ByteArrayOutPutStream y guardarlo como String en SharedPreferences
rallat

27
otra opción se guarda como json y luego se asigna de nuevo. Con GSON o jackSON es realmente fácil
rallat

2
déjame llevar mi máquina del tiempo a 2011 y averiguarlo
Blundell

324

Sí, podemos hacer esto usando Gson

Descargar código de trabajo de GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

Para salvar

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

Olvidar

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

Actualización1

La última versión de GSON se puede descargar desde github.com/google/gson .

Actualización2

Si está utilizando Gradle / Android Studio, simplemente coloque lo siguiente en build.gradlela sección de dependencias:

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

no funciona en mi caso. Incluso después de poner jar en libs y configurar en la ruta de construcción, la clase Gson no se resuelve.
Shirish Herwade

Proyecto limpio y luego prueba @ShirishHerwade
Parag Chauhan

@parag que tampoco funciona. ¿Puede decirme los pasos para usar ese frasco para eliminar el error anterior? Debido a que agregué con éxito ese jar en la carpeta libs y luego en la "ruta de compilación de java", también intenté agregar json de almacenamiento externo en mi escritorio
Shirish Herwade

7
Esta respuesta sería aún mejor si también mencionara sus limitaciones. ¿Qué tipo de objeto podemos y no podemos almacenar y recuperar de esta manera? Obviamente, no funcionará para todas las clases.
wvdz

3
String json = gson.toJson("MyObject");debe ser el objeto, no una cadena.
Ahmed Hegazy

44

podemos usar Outputstream para enviar nuestro objeto a la memoria interna. Y convierta a cadena y luego guárdelo de preferencia. Por ejemplo:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

cuando necesitamos extraer Object de Preference. Utilice el código de la siguiente manera

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();

Hola, sé que esto se publicó hace un tiempo, pero ¿estás seguro de que el código que tienes para extraer el objeto almacenado es correcto? Recibo múltiples errores en las últimas 2 líneas quejándose de cómo los constructores explícitos deben definirse en lugar de simplemente tener "new ObjectInputStream (byteArray)". ¡Gracias por la ayuda!
Wakka Wakka Wakka

Hola, de repente recibo una EOFException en in = new ObjectInputStream (base64InputStream); Lo estoy escribiendo en preferencias compartidas exactamente de la misma manera que lo estás haciendo. ¿Qué crees que podría estar mal?
marienke

¿Tiene alguna excepción cuando escribe Objeto en pref? Desde SDK: EOFException lanzada cuando un programa encuentra el final de un archivo o flujo durante una operación de entrada.
Kislingk

Felicitaciones, esta es la mejor solución que encontré para este problema hasta ahora. Sin dependencias. Sin embargo, debe tenerse en cuenta que para poder usar ObjectOutput / InputStream para un objeto, dicho objeto y todos los objetos personalizados dentro de él deben implementar la interfaz serializable.
user1112789

8

Tuve el mismo problema, aquí está mi solución:

Tengo la clase MyClass y ArrayList <MyClass> que quiero guardar en Preferencias compartidas. Al principio, agregué un método a MyClass que lo convierte en un objeto JSON:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

Entonces aquí está el método para guardar el objeto "ArrayList <MyClass> items":

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
    SharedPreferences.Editor editor = mPrefs.edit();

    Set<String> set= new HashSet<String>();
    for (int i = 0; i < items.size(); i++) {
        set.add(items.get(i).getJSONObject().toString());
    }

    editor.putStringSet("some_name", set);
    editor.commit();

Y aquí está el método para recuperar el objeto:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

Tenga en cuenta que StringSet en Shared Preferences está disponible desde API 11.


Resolvió mi problema. Quiero agregar algo. Para el primer uso debemos comprobar si el conjunto es nulo. if (set! = null) {for (String s: set) {..}}
xevser

@xevser He agregado una verificación nula como se sugirió. Gracias.
Micer

6

Usando la biblioteca Gson:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

Tienda:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

Recuperar:

String json = getPrefs().getUserJson();

Parcel no es un mecanismo de serialización de propósito general. Esta clase (y la API Parcelable correspondiente para colocar objetos arbitrarios en una Parcela) está diseñada como un transporte IPC de alto rendimiento. Como tal, no es apropiado colocar ningún dato de Parcela en un almacenamiento persistente: los cambios en la implementación subyacente de cualquiera de los datos de Parcel pueden hacer que los datos más antiguos sean ilegibles.
Marcos Vasconcelos

1

¡Puedes hacerlo usando la PowerPreferencebiblioteca en 3 sencillos pasos!

https://github.com/AliAsadi/PowerPreference

1. Crear objeto

Object obj = new Object();

2. Escriba a preferencia compartida

PowerPreference.getDefaultFile().put("object",obj);

3. Obtener el objeto

Object obj = PowerPreference.getDefaultFile()
                            .getObject("object", Object.class);

0

Usar este objeto -> TinyDB - Android-Shared-Preferences-Turbo es muy simple. puede guardar la mayoría de los objetos de uso común con él, como matrices, enteros, listas de cadenas, etc.


Genial, pero creo que esto solo funciona para tipos primitie (String, double, int, etc.) no para objetos personalizados (POJOS)
CommonSenseCode

ahora funciona para objetos personalizados, verifique el archivo Léame, se ha actualizado
kc ochibili

0

Puede utilizar Complex Preferences Android - por la biblioteca de Felipe Silvestre para almacenar sus objetos personalizados. Básicamente, utiliza el mecanismo GSON para almacenar objetos.

Para guardar el objeto en preferencias:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

Y para recuperarlo:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);

Parcel no es un mecanismo de serialización de propósito general. Esta clase (y la API Parcelable correspondiente para colocar objetos arbitrarios en una Parcela) está diseñada como un transporte IPC de alto rendimiento. Como tal, no es apropiado colocar ningún dato de Parcela en un almacenamiento persistente: los cambios en la implementación subyacente de cualquiera de los datos de Parcel pueden hacer que los datos más antiguos sean ilegibles.
Marcos Vasconcelos

Esto está en desuso
IgorGanapolsky

0

Podría usar GSON, usando Gradle Build.gradle:

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

Luego, en su código, por ejemplo, pares de cadena / booleano con Kotlin:

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

Agregar a SharedPrefs:

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

Ahora para recuperar datos:

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}

Parcel no es un mecanismo de serialización de propósito general. Esta clase (y la API Parcelable correspondiente para colocar objetos arbitrarios en una Parcela) está diseñada como un transporte IPC de alto rendimiento. Como tal, no es apropiado colocar ningún dato de Parcela en un almacenamiento persistente: los cambios en la implementación subyacente de cualquiera de los datos de Parcel pueden hacer que los datos más antiguos sean ilegibles.
Marcos Vasconcelos

0

Preferencia compartida común (CURD) SharedPreference: para almacenar datos en forma de pares de valor-clave con una clase Kotlin simple.

var sp = SharedPreference(this);

Almacenamiento de datos:

Para almacenar datos String, Int y Boolean tenemos tres métodos con el mismo nombre y diferentes parámetros (Method overloading).

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

Recuperar datos: para recuperar los datos almacenados en SharedPreferences, utilice los siguientes métodos.

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

Borrar todos los datos: para borrar todas las preferencias compartidas, utilice el siguiente código.

 sp.clearSharedPreference()

Eliminar datos específicos:

sp.removeValue("user_name")

Clase de preferencia compartida común

import android.content.Context
import android.content.SharedPreferences

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

Blog: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html


-2

No hay forma de almacenar objetos en SharedPreferences, lo que hice fue crear una clase pública, poner todos los parámetros que necesito y crear setters y getters, pude acceder a mis objetos,


-3

¿Necesita recuperar el objeto incluso después de que la aplicación se cerró o simplemente durante su ejecución?

Puede almacenarlo en una base de datos.
O simplemente cree una clase de aplicación personalizada.

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

Y luego de cada actividad haz:

((MyApplication) getApplication).getMyObject();

No es realmente la mejor manera, pero funciona.


-6

Sí. Puede almacenar y recuperar el objeto utilizando Sharedpreference

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.