5

I have a problem with storing string set preference. I have these utility methods for storing:

public static void putStringSet(SharedPreferences pref, Editor e, String key, Set<String> set)
{
    if (Utils.isApiLevelGreaterThanGingerbread())
    {
        // e.remove(key); // I tried to remove it here
        e.putStringSet(key, set);
    }
    else
    {
        // removes old occurences of key
        for (String k : pref.getAll().keySet())
        {
            if (k.startsWith(key))
            {
                e.remove(k);
            }
        }

        int i = 0;
        for (String value : set)
        {
            e.putString(key + i++, value);
        }
    }
}

public static Set<String> getStringSet(SharedPreferences pref, String key, Set<String> defaultValue)
{
    if (Utils.isApiLevelGreaterThanGingerbread())
    {
        return pref.getStringSet(key, defaultValue);
    }
    else
    {
        Set<String> set = new HashSet<String>();

        int i = 0;

        Set<String> keySet = pref.getAll().keySet();
        while (keySet.contains(key + i))
        {
            set.add(pref.getString(key + i, ""));
            i++;
        }

        if (set.isEmpty())
        {
            return defaultValue;
        }
        else
        {
            return set;
        }
    }
}

I use these methods to be backward compatible with GB. But I have a problem that using putStringSet method isn't persistent for API > gingerbread. It is persistent while app is runing. But it dissapears after restart. I will describe the steps:

  1. Clean install of application - there is no preference with key X
  2. I store string set A with key X - preference contains A
  3. I store string set B with key X - preference contains B
  4. Close app
  5. Restart of app - preference contains A
  6. I store string set C with key X - preference contains C
  7. Close app
  8. Restart of app - preference contains A

So only the first value is persistent and I cannot overwrite it.

Other notes:

  1. this methods just replaces putStringSet and getStringSet. So I use commit()...but elsewhere (see example below).
  2. I tried to replace commit() with apply() - no success
  3. When I use code for older APIs in newer APIs (I commented first 4 lines in both methods) it works flawlessly but it isn't so efficient

Example of use:

Editor e = mPref.edit();
PreferencesUtils.putStringSet(mPref, e, GlobalPreferences.INCLUDED_DIRECTORIES, dirs);
e.commit();

Thnak you very much for help.

Bhiefer
  • 1,613
  • 4
  • 16
  • 31

2 Answers2

8

This has a ridiculous amount of duplicates - I bet that you do :

set = prefs.getStringSet("X", new HashSet<String>());
set.add("yada yada");
prefs.putStringSet("X", set);

In short android sees that set and the one inside refer to the same set and does nothing. Correct ?

See: Misbehavior when trying to store a string set using SharedPreferences

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

My condition is very similar to yours, the only difference is when restart the app, preference contains A, B, C, but when reinstall it or reboot the phone, B&C are gone.

I also tried replace commit() with apply(), as this post adviced SharedPreferences not persistent , but still not to work.

I solved this problem by remove & commit the preference before replacing it:

editor.remove("StringSetKey");
editor.commit();

editor.putStringSet("StringSetKey", newSet);
editor.commit();

Ps: you can type adb pull /data/data/<packagename>/shared_prefs/xxxx.xml in cmd line to see if the commit() really works

Pps: I think this is a bug with putStringSet....

hope this will help you ;)

Community
  • 1
  • 1
zhangxaochen
  • 32,744
  • 15
  • 77
  • 108
  • I give you a -1 because all you had to do was read the [javadoc for getStringSet()](http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet%28java.lang.String,%20java.util.Set%3Cjava.lang.String%3E%29): _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._ And when you face a problem the solution is not hacks - but understanding what goes on. _Why do you have to remove the set and re-add it ? Does it really make sense to you ?_ – Mr_and_Mrs_D Feb 01 '14 at 11:36
  • Edit your answer to be correct and will undo my vote – Mr_and_Mrs_D Feb 02 '14 at 10:02