memorizzare e recuperare un oggetto di classe nelle preferenze condivise


111

In Android possiamo memorizzare un oggetto di una classe nella preferenza condivisa e recuperare l'oggetto in un secondo momento?

Se è possibile come si fa? Se non è possibile quali sono le altre possibilità per farlo?

So che la serializzazione è un'opzione, ma cerco possibilità utilizzando la preferenza condivisa.


Aggiungo una libreria di supporto nel caso qualcuno ne abbia bisogno: github.com/ionull/objectify
Tsung Goh


Ecco una risposta a una domanda simile.
tpk


Puoi usare questa libreria che ha molte funzioni integrate. github.com/moinkhan-in/PreferenceSpider
Moinkhan

Risposte:


15

Non possibile.

È possibile memorizzare solo valori semplici in SharedPrefences SharePreferences.Editor

Che cosa in particolare della classe devi salvare?


1
Grazie.Voglio memorizzare alcuni membri di dati della classe.E non voglio memorizzare ogni valore dei membri di dati usando la preferenza condivisa.Voglio memorizzarlo come un oggetto.Se non preferenza condivisa quali sono le mie altre opzioni?
androidGuy

5
Serializzalo e memorizzalo, in un database (SQLite) / in un file flat.
Blundell

5
La risposta non è completa. La possibile soluzione è trasformare il pojo in ByteArrayOutPutStream e salvarlo come String nelle SharedPreferences
rallat

27
un'altra opzione viene salvata come json e quindi mappata di nuovo. Con GSON o jackSON è davvero facile
rallat il

2
fammi riportare la mia macchina del tempo al 2011 e capirlo
Blundell

324

Sì, possiamo farlo usando Gson

Scarica il codice funzionante da GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

Per salvare

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

Dimenticare

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

Update1

L'ultima versione di GSON può essere scaricata da github.com/google/gson .

Update2

Se stai usando Gradle / Android Studio, inserisci quanto segue nella build.gradlesezione delle dipendenze -

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

non funziona nel mio caso. Anche dopo aver inserito jar nelle librerie e impostato nel percorso di compilazione, la classe Gson non viene risolta.
Shirish Herwade

Progetto pulito, quindi prova @ShirishHerwade
Parag Chauhan

@parag che anche non funziona. Puoi dirmi i passaggi per utilizzare quel barattolo per rimuovere l'errore sopra. Poiché ho aggiunto con successo quel jar nella cartella libs e poi in "java build path" ho anche provato ad aggiungere json per l'archiviazione esterna sul mio desktop
Shirish Herwade,

7
Questa risposta sarebbe ancora migliore se menzionasse anche i suoi limiti. Che tipo di oggetto possiamo e non possiamo immagazzinare e recuperare in questo modo? Ovviamente non funzionerà per tutte le classi.
wvdz

3
String json = gson.toJson("MyObject");dovrebbe essere l'oggetto non una stringa.
Ahmed Hegazy

44

possiamo usare Outputstream per inviare il nostro Object alla memoria interna. E converti in stringa, quindi salva di preferenza. Per esempio:

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

quando dobbiamo estrarre Object da Preference. Usa il codice come sotto

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

Ciao, so che è stato pubblicato tempo fa, ma sei sicuro che il codice che hai per estrarre l'oggetto memorizzato sia corretto? Ricevo più errori nelle ultime 2 righe che si lamentano di come i costruttori espliciti debbano essere definiti piuttosto che avere semplicemente "new ObjectInputStream (byteArray)". Grazie per l'aiuto!
Wakka Wakka Wakka

Salve, improvvisamente ricevo un'EOFException su in = new ObjectInputStream (base64InputStream); Lo sto scrivendo a preferenze condivise esattamente nello stesso modo in cui lo stai facendo. Cosa pensi possa essere sbagliato?
marienke

Hai qualche eccezione quando scrivi Object in pref? Da SDK: generata EOFException quando un programma incontra la fine di un file o di un flusso durante un'operazione di input.
Kislingk

Complimenti, questa è la migliore soluzione che ho trovato finora per questo problema. Nessuna dipendenza. Tuttavia, va notato che per poter utilizzare ObjectOutput / InputStream per un oggetto, detto oggetto e tutti gli oggetti personalizzati al suo interno devono implementare l'interfaccia Serializable.
user1112789

8

Ho avuto lo stesso problema, ecco la mia soluzione:

Ho la classe MyClass e ArrayList <MyClass> che voglio salvare nelle Preferenze condivise. All'inizio ho aggiunto un metodo a MyClass che lo converte in oggetto 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;
}

Quindi ecco il metodo per salvare l'oggetto "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();

Ed ecco il metodo per recuperare l'oggetto:

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

Tieni presente che StringSet in Preferenze condivise è disponibile dall'API 11.


Ho risolto il mio problema. Voglio aggiungere qualcosa. Per il primo utilizzo dobbiamo verificare se l'insieme è nullo. if (set! = null) {for (String s: set) {..}}
xevser

@xevser Ho aggiunto il controllo nullo come suggerito. Grazie.
Micer

6

Utilizzando Gson Library:

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

Negozio:

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

Recuperare:

String json = getPrefs().getUserJson();

Parcel non è un meccanismo di serializzazione generico. Questa classe (e la corrispondente API Parcelable per il posizionamento di oggetti arbitrari in un Parcel) è progettata come trasporto IPC ad alte prestazioni. In quanto tale, non è appropriato collocare i dati di Parcel in una memoria persistente: le modifiche all'implementazione sottostante di uno qualsiasi dei dati nel Parcel possono rendere illeggibili i dati precedenti.
Marcos Vasconcelos

1

Puoi farlo utilizzando la PowerPreferencelibreria in 3 semplici passaggi!

https://github.com/AliAsadi/PowerPreference

1. Crea oggetto

Object obj = new Object();

2. Scrivi nella preferenza condivisa

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

3. Ottenere l'oggetto

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

0

Utilizzando questo oggetto -> TinyDB - Android-Shared-Preferences-Turbo è molto semplice. puoi salvare la maggior parte degli oggetti di uso comune con esso come array, numeri interi, elenchi di stringhe ecc


Fantastico, ma penso che funzioni solo per i tipi di primitie (String, double, int, ecc.) Non per gli oggetti personalizzati (POJOS)
CommonSenseCode

ora funziona per oggetti personalizzati, controlla il ReadMe, è stato aggiornato
kc ochibili

0

Puoi utilizzare la libreria Complex Preferences Android - by Felipe Silvestre per memorizzare i tuoi oggetti personalizzati. Fondamentalmente, utilizza il meccanismo GSON per memorizzare gli oggetti.

Per salvare l'oggetto nelle preferenze:

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

E per recuperarlo:

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

Parcel non è un meccanismo di serializzazione generico. Questa classe (e la corrispondente API Parcelable per il posizionamento di oggetti arbitrari in un Parcel) è progettata come trasporto IPC ad alte prestazioni. In quanto tale, non è appropriato collocare i dati di Parcel in una memoria persistente: le modifiche all'implementazione sottostante di uno qualsiasi dei dati nel Parcel possono rendere illeggibili i dati precedenti.
Marcos Vasconcelos

Questo è deprecato
IgorGanapolsky

0

Puoi usare GSON, usando Gradle Build.gradle:

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

Quindi nel tuo codice, ad esempio coppie di string / boolean 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)

Aggiunta a SharedPrefs:

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

Ora per recuperare i dati:

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 non è un meccanismo di serializzazione generico. Questa classe (e la corrispondente API Parcelable per il posizionamento di oggetti arbitrari in un Parcel) è progettata come trasporto IPC ad alte prestazioni. In quanto tale, non è appropriato collocare i dati di Parcel in una memoria persistente: le modifiche all'implementazione sottostante di uno qualsiasi dei dati nel Parcel possono rendere illeggibili i dati precedenti.
Marcos Vasconcelos

0

Preferenza condivisa comune (CURD) SharedPreference: per memorizzare i dati sotto forma di coppie valore-chiave con una semplice classe Kotlin.

var sp = SharedPreference(this);

Memorizzazione dei dati:

Per memorizzare i dati String, Int e Boolean abbiamo tre metodi con lo stesso nome e parametri differenti (Method overloading).

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

Recupera dati: per recuperare i dati archiviati in SharedPreferences utilizzare i seguenti metodi.

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

Cancella tutti i dati: per cancellare l'intero SharedPreferences utilizzare il codice seguente.

 sp.clearSharedPreference()

Rimuovi dati specifici:

sp.removeValue("user_name")

Classe di preferenza condivisa comune

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

Non c'è modo di memorizzare oggetti in SharedPreferences, quello che ho fatto è creare una classe pubblica, inserire tutti i parametri di cui ho bisogno e creare setter e getter, sono stato in grado di accedere ai miei oggetti,


-3

Hai bisogno di recuperare l'oggetto anche dopo che l'applicazione ha chiuso donw o solo durante l'esecuzione?

Puoi salvarlo in un database.
Oppure crea semplicemente una classe di applicazione personalizzata.

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>

E poi da ogni attività fai:

((MyApplication) getApplication).getMyObject();

Non proprio il modo migliore, ma funziona.


-6

Sì. Puoi memorizzare e recuperare l'oggetto utilizzando Sharedpreference

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.