user2313423
user2313423

Reputation: 755

Android SharedPreferences String Set - some items are removed after app restart

I save a string set in the shared preferences, if I read it out it's ok. I start other activities, go back and read it again, it's ok. If I close the application, and start it again, I get the set, but with only 1 item instead of 4. It happens all the time. Is there a known issue? What could I do wrong?

In a class, what is created in the application's oncreate method I have a SharedPreferences and a SharePreferences.Editor variable. I use them in the save and load methods.

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

I just can't understand how could it happen, to store perfectly all items while the app is running, then after a restart not all items are in the set. And I think if all items are removed it could be more acceptable than some items are gone, and one item is still there. Is there an explanation?

Upvotes: 38

Views: 22480

Answers (7)

김성무
김성무

Reputation: 1

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, null);
    ed.commit();
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, feedbackSet);
    ed.commit();
}

Upvotes: 0

AnAndroid
AnAndroid

Reputation: 567

To save string in sharedprefernces

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

To retrieve data from shared preference

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

Upvotes: -1

Jaden Gu
Jaden Gu

Reputation: 9283

This "problem" is documented on SharedPreferences.getStringSet().

getStringSet() returns a reference of the stored HashSet object inside SharedPreferences. When you add elements to this object, they are added in fact inside SharedPreferences.

The workaround is making a copy of the returned Set and putting the new Set into SharedPreferences. I tested it and it works.

In Kotlin, that would be

    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

Upvotes: 22

Dave Justen
Dave Justen

Reputation: 149

Ran into this same problem. Solved it by clearing the editor after instantiating and before committing.

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

I tried creating a copy as others suggested, but that didn't work for me.

Found this solution here.

Upvotes: 1

Branko Riznić
Branko Riznić

Reputation: 161

Try to create Copy of your set, and than you can save it in same prefs:

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

Upvotes: 9

s-hunter
s-hunter

Reputation: 25826

According to the document, the String Set in SharedPreferences should treated as immutable, things go south when trying to modify it. A work around would be: Get the existing set, make a copy of it, update the copy and then save it back to the shared preferences like it was a new set.

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

Upvotes: 0

Madhur Ahuja
Madhur Ahuja

Reputation: 22709

Based on your question, you should call commit only after 4 items have been added to the set. In your code, you are calling commit for each feedback which will overwrite the previous feedback.

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.

This is exactly what you are doing

Upvotes: 31

Related Questions