2012-12-25 14 views
51

Sto tentando di memorizzare una serie di stringhe usando SharedPreferences API.Comportamento scorretto durante il tentativo di memorizzare una serie di stringhe usando SharedPreferences

Set<String> s = sharedPrefs.getStringSet("key", new HashSet<String>()); 
s.add(new_element); 

SharedPreferences.Editor editor = sharedPrefs.edit(); 
editor.putString(s); 
edit.commit() 

La prima volta che eseguire il codice sopra, s viene impostato al valore di default (fine appena creato vuoto HashSet) ed è memorizzata senza problemi.

La seconda e la prossima volta che eseguo questo codice, un oggetto s viene restituito con il primo elemento aggiunto. Posso aggiungere l'elemento e, durante l'esecuzione del programma, è apparentemente memorizzato nello SharedPreferences, ma quando il programma viene ucciso, lo SharedPreferences rilegge dalla sua memoria persistente e i valori più recenti vengono persi.

In che modo il secondo e gli elementi successivi possono essere memorizzati in modo da non perdersi?

+1

il codice non deve essere chiamato editor.putStringSet()? – bluehallu

risposta

118

Questo "problema" è documentato su SharedPreferences.getStringSet.

Il SharedPreferences.getStringSet restituisce un riferimento dell'oggetto HashSet memorizzato all'interno dello SharedPreferences. Quando aggiungi elementi a questo oggetto, vengono aggiunti di fatto all'interno dello SharedPreferences.

Che è ok, ma il problema nasce quando si tenta di salvarlo: Android confronta la HashSet modificato che si sta tentando di salvare utilizzando SharedPreferences.Editor.putStringSet con quello attuale memorizzata sul SharedPreference, ed entrambi sono lo stesso oggetto !!!

Una possibile soluzione è quella di effettuare una copia del Set<String> restituito dall'oggetto SharedPreferences:

Set<String> s = new HashSet<String>(sharedPrefs.getStringSet("key", new HashSet<String>())); 

Ciò rende s un oggetto diverso, e le corde aggiunte per s non verranno aggiunti al set immagazzinata all'interno il SharedPreferences.

Un'altra soluzione alternativa è quella di utilizzare la stessa transazione SharedPreferences.Editor per memorizzare un'altra preferenza più semplice (come un numero intero o booleano), l'unica cosa necessaria è forzare che il valore memorizzato sia diverso su ciascuna transazione (ad esempio è possibile memorizzare le dimensioni del set di stringhe).

+3

Ho già fatto +1, ma potresti fornire un link alla fonte di backup del tuo reclamo che: "Android confronta l'HashSet modificato che stai cercando di salvare usando SharedPreferences.Editor.putStringSet con quello corrente memorizzato in SharedPreference" –

+1

Been sbattendo la testa contro un muro tutto il giorno su questo! Grazie!!! – Tim

+0

La seconda opzione (salvare un contatore) ha funzionato bene per me. Grazie! – MarionaDSR

12

Questo comportamento viene documentato in modo legato alla progettazione:

da getStringSet:.

"Si noti che non è necessario modificare l'istanza set restituito da questa chiamata La consistenza dei dati memorizzati non è garantito se lo fai, né la tua capacità di modificare l'istanza. "

E sembra abbastanza ragionevole specialmente se è documentato nell'API, altrimenti questa API dovrebbe fare copia su ogni accesso. Quindi la ragione di questo design era probabilmente la performance. Suppongo che dovrebbero rendere questa funzione restituita il risultato avvolto in un'istanza di classe non modificabile, ma questo richiede ancora una volta l'allocazione.

+2

Ho modificato la mia risposta questo pomeriggio. Mi sono reso conto che è correttamente documentato, ma quando si scrive codice molte volte non si guarda alla documentazione in cose del genere. Questa è l'unica ragione per continuare a chiedere + risposta, IMHO, perché è una classe di utilità e questo tipo di spiegazione può aiutare chiunque. Grazie anche per il tuo chiarimento – JoseLSegura

2

era alla ricerca di una soluzione per lo stesso problema, risolto facendo:

1) recuperare il set esistente dalle preferenze condivise

2) Creare una copia di esso

3) Aggiornamento la copia

4) Salvare la copia

SharedPreferences.Editor editor = sharedPrefs.edit(); 
Set<String> oldSet = sharedPrefs.getStringSet("key", new HashSet<String>()); 

//make a copy, update it and save it 
Set<String> newStrSet = new HashSet<String>();  
newStrSet.add(new_element); 
newStrSet.addAll(oldSet); 

editor.putStringSet("key",newStrSet); edit.commit(); 

Why

0

Ho provato tutte le risposte di cui sopra non ha funzionato per me. Così ho fatto le seguenti operazioni

  1. prima di aggiungere nuovo elemento alla lista dei vecchi pref condiviso, fare una copia di esso
  2. chiamata di un metodo con la copia di cui sopra come un param a tale metodo.
  3. all'interno di quel metodo deselezionare il pref condiviso che contiene quei valori.
  4. aggiungere i valori presenti in copia alla preferenza condivisa deselezionata che lo tratterà come nuovo.

    public static void addCalcsToSharedPrefSet(Context ctx,Set<String> favoriteCalcList) { 
    
    ctx.getSharedPreferences(FAV_PREFERENCES, 0).edit().clear().commit(); 
    
    SharedPreferences sharedpreferences = ctx.getSharedPreferences(FAV_PREFERENCES, Context.MODE_PRIVATE); 
    SharedPreferences.Editor editor = sharedpreferences.edit(); 
    editor.putStringSet(FAV_CALC_NAME, favoriteCalcList); 
    editor.apply(); } 
    

stavo affrontando problema con i valori non essere persistente, se riapro l'applicazione dopo la pulizia l'applicazione da sfondo solo primo elemento aggiunto alla lista è stato mostrato.

Problemi correlati