web-dev-qa-db-fra.com

Android SharedPreferences String Set - certains éléments sont supprimés après le redémarrage de l'application

Je sauvegarde un ensemble de chaînes dans les préférences partagées. Si je le lis, tout va bien. Je commence d'autres activités, retourne en arrière et relis-le, c'est bon. Si je ferme l'application et la redémarre, je récupère l'ensemble, mais avec un seul élément au lieu de 4. Cela se produit tout le temps. Y a-t-il un problème connu? Que pourrais-je faire de mal?

Dans une classe, ce qui est créé dans la méthode oncreate de l'application a une variable SharedPreferences et une variable SharePreferences.Editor. Je les utilise dans les méthodes de sauvegarde et de chargement.

public void saveFeedback(FeedbackItem feedbackItem) {
    checkSp();
    Set<String> feedbackSet = getFeedbacksSet();
    if(feedbackSet == null){
        feedbackSet = new HashSet<String>();
    }
    JSONObject json = createJSONObjectfromFeedback(feedbackItem);
    feedbackSet.add(json.toString());
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, feedbackSet);
    ed.commit();
}

public Set<String> getFeedbacksSet(){
    checkSp();
    Set<String> ret = sp.getStringSet(CoreSetup.KEY_FEEDBACK, null);
    return ret;
}

private void checkSp(){
    if(this.sp == null)
        this.sp = applicationContext.getSharedPreferences(applicationContext.getPackageName(), Context.MODE_PRIVATE);
    if(this.ed == null)
        this.ed = this.sp.edit();
}

Je ne comprends tout simplement pas comment cela pourrait se produire: stocker parfaitement tous les éléments lorsque l'application est en cours d'exécution, puis après un redémarrage, tous les éléments ne sont pas dans l'ensemble. Et je pense que si tous les éléments sont supprimés, cela pourrait être plus acceptable que certains éléments ont disparu, et un élément est toujours là. Y a-t-il une explication?

32
user2313423

Selon votre question, vous ne devez appeler commit que lorsque 4 éléments ont été ajoutés à l'ensemble. Dans votre code, vous appelez commit pour chaque commentaire qui écrasera le commentaire précédent.

Update: http://developer.Android.com/reference/Android/content/SharedPreferences.html#getStringSet(Java.lang.String , Java.util.Set)

Note that you must not modify the set instance returned by this call. The consistency of the stored data is not guaranteed if you do, nor is your ability to modify the instance at all.

C'est exactement ce que vous faites

27
Madhur Ahuja

Ce "problème" est documenté sur SharedPreferences.getStringSet() .

getStringSet () renvoie une référence à l'objet HashSet stocké dans SharedPreferences. Lorsque vous ajoutez des éléments à cet objet, ils sont ajoutés en fait inside SharedPreferences.

La solution de contournement consiste à copier le jeu renvoyé et à le placer dans SharedPreferences. Je l'ai testé et ça marche.

À Kotlin, ce serait

    val setFromSharedPreferences = sharedPreferences.getStringSet("key", mutableSetOf())
    val copyOfSet = setFromSharedPreferences.toMutableSet()
    copyOfSet.add(addedString)

    val editor = sharedPreferences.edit()
    editor.putStringSet("key", copyOfSet)
    editor.apply() // or commit() if really needed
17
Jaden Gu

Essayez de créer une copie de votre ensemble, et que vous pouvez l'enregistrer dans les mêmes préférences:

private Set<String> _setFromPrefs;


public void GetSetFromPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    Set<String> someSets = sharedPref.getStringSet("some_sets", new HashSet<String>() );
    _setFromPrefs = new HashSet<>(someSets); // THIS LINE CREATE A COPY
}


public void SaveSetsInPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putStringSet("some_sets", _setFromPrefs);
    editor.commit();
}
5
Branko Riznić

Couru dans ce même problème. Résolu le problème en effaçant l'éditeur après l'instanciation et avant la validation.

sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    sFavList = sPrefs.getStringSet(context.getResources().getString(R.string.pref_fav_key), null);
    sEditor = sPrefs.edit();
    sEditor.clear(); // added clear, now Set data persists as expected
    if (sFavList == null) sFavList = new HashSet<>();
    sFavList.add(title);
    sEditor.putStringSet(context.getResources().getString(R.string.pref_fav_key), sFavList).apply();

J'ai essayé de créer une copie comme d'autres l'ont suggéré, mais cela ne m'a pas fonctionné.

Trouvé cette solution ici .

0
Dave Justen

Selon le document, le jeu de chaînes dans SharedPreferences devrait être considéré comme immuable, les choses vont mal lorsque nous essayons de le modifier. Voici un moyen de contourner le problème: .__ Obtenez le jeu existant, en faites une copie, mettez-le à jour, puis enregistrez-le dans les préférences partagées comme s'il s'agissait d'un nouveau jeu.

Set<String> feedbackSet = getFeedbacksSet();
if(feedbackSet == null){
    feedbackSet = new HashSet<String>();
}

//make a copy of the set, update the copy and save the copy
Set<String> newFeedbackSet = new HashSet<String>();
JSONObject json = createJSONObjectfromFeedback(feedbackItem);
newFeedbackSet.add(json.toString());
newFeedbackSet.addAll(feedbackSet);
ed.putStringSet(CoreSetup.KEY_FEEDBACK, newFeedbackSet);
ed.commit();
0
s-hunter

Pour enregistrer une chaîne dans sharedprefernces

   SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this);
   editor.putString("text", mSaved.getText().toString());
   editor.commit();

Pour récupérer des données à partir d'une préférence partagée

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 String restoredText = prefs.getString("text", null);
0
AnAndroid