16

I need to put Set in SharedPreference, but I have a problem.

when I click button, I will get Set from SharedPreference and add data to Set then put back SharedPreference, but when I destroy project and open it again, the sharedPreference only get one string in Set

SharedPreferences s = getSharedPreferences("db", 0);
Log.i("chauster", "1.set = "+s.getStringSet("set", new HashSet<String>()));

Button btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener(new Button.OnClickListener() {

    @Override
    public void onClick(View v) {
        SharedPreferences ss = getSharedPreferences("db", 0);
        Set<String> hs = ss.getStringSet("set", new HashSet<String>());
        hs.add(String.valueOf(hs.size()+1));
        Editor edit = ss.edit();
        edit.putStringSet("set", hs);
        edit.commit();
        SharedPreferences sss = getSharedPreferences("db", 0);
        Log.i("chauster", "2.set = "+sss.getStringSet("set",
                new HashSet<String>()));
    }
});

when I install project first, and I click button 4 times, the logcat print it

1.set = []
2.set = [1]
2.set = [2, 1]
2.set = [3, 2, 1]
2.set = [3, 2, 1, 4]

it's look like success to put string in sharedPreference Set, but when I destroy app and open it again, the logcat print it

1.set = [1]

it means only one string in Set from sharedPreference, I don't know what's happened? Please help me. thanks~

henry4343
  • 3,871
  • 5
  • 22
  • 30

4 Answers4

62

You fell to the usual trap of editing the value you got from getStringSet(). This is forbidden in the docs

You should :

SharedPreferences ss = getSharedPreferences("db", 0);
Set<String> hs = ss.getStringSet("set", new HashSet<String>());
Set<String> in = new HashSet<String>(hs);
in.add(String.valueOf(hs.size()+1));
ss.edit().putStringSet("set", in).commit(); // brevity
// SharedPreferences sss = getSharedPreferences("db", 0); // not needed
Log.i("chauster", "2.set = "+ ss.getStringSet("set", new HashSet<String>()));

For a half baked explanation see : Misbehavior when trying to store a string set using SharedPreferences

Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
3

use edit.clear() before putStringSet

SharedPreferences ss = getSharedPreferences("db", 0);
Set<String> hs = ss.getStringSet("set", new HashSet<String>());
hs.add(String.valueOf(hs.size()+1));
Editor edit = ss.edit();
edit.clear();
edit.putStringSet("set", hs);
edit.commit();
2

Remove the key for HashSet in SharedPreferences, commit then add new value.

SharedPreferences ss;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_third);
    ss = getSharedPreferences("db", 0);
    fun();
}

void fun() {
    Log.i("chauster", "1.set = "+ss.getStringSet("set", new HashSet<String>()));

    Button btn = (Button)findViewById(R.id.btn);
    btn.setOnClickListener(new Button.OnClickListener() {

        @Override
        public void onClick(View v) {
            Set<String> hs = ss.getStringSet("set", new HashSet<String>());
            hs.add(String.valueOf(hs.size()+1));
            Log.i(TAG, "list: " + hs.toString());
            Editor edit = ss.edit();
            edit.remove("set");
            edit.commit();
            edit.putStringSet("set", hs);
            Log.i(TAG, "saved: " + edit.commit());

            Log.i("chauster", "2.set = "+ss.getStringSet("set", new HashSet<String>()));
        }
    });
}
Krrishnaaaa
  • 689
  • 11
  • 23
0

Folks, I'm keeping it here for historical reasons. Do not use this approach! (What use is it? It shows how bad code appears: the API behaves counter-intuitively, there is a gotcha, a developer tries to work-around the gotcha. Bad code appears. Later, the gotcha gets officially documented, and a different workaround is suggested, but the bad code gets shared.)


Try to store SharedPreferences to a static variable instead of invoking getSharedPreferences each time. This sounds terrible, but this worked for me once.

public class Prefs {
    // this singleton is a workaround for an Android bug:
    // two SharedPreferences objects do not see changes in each other.
    private static SharedPreferences theSingletone;
    public static SharedPreferences get(Activity from) {
        //PreferenceManager.getDefaultSharedPreferences(getContext());
        if (theSingletone == null) {
            theSingletone = from.getApplicationContext().getSharedPreferences("prefs", Context.MODE_PRIVATE);
        }
        return theSingletone;
    }
}
18446744073709551615
  • 16,368
  • 4
  • 94
  • 127