Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Misbehavior when trying to store a string set using SharedPreferences

I'm trying to store a set of strings using the SharedPreferences API.

Set<String> s = sharedPrefs.getStringSet("key", new HashSet<String>()); s.add(new_element);  SharedPreferences.Editor editor = sharedPrefs.edit(); editor.putStringSet(s); edit.commit() 

The first time I execute the code above, s is set to the default value (the just created end empty HashSet) and it is stored without problems.

The second and next times I execute this code, a s object is returned with the first element added. I can add the element, and during the program execution, it is apparently stored in the SharedPreferences, but when the program is killed, the SharedPreferences read again from its persistent storage and the newer values are lost.

How can the second, and elements after that, be stored so they won't get lost?

like image 271
JoseLSegura Avatar asked Dec 25 '12 23:12

JoseLSegura


People also ask

Is SharedPreferences thread safe?

The SharedPreferences implementation in Android is thread-safe but not process-safe. Normally your app will run all in the same process, but it's possible for you to configure it in the AndroidManifest.

What is the method used to store and retrieve data on the SharedPreferences?

Shared Preferences allow you to save and retrieve data in the form of key,value pair. In order to use shared preferences, you have to call a method getSharedPreferences() that returns a SharedPreference instance pointing to the file that contains the values of preferences.

Can we store objects in SharedPreferences?

We can store fields of any Object to shared preference by serializing the object to String.


1 Answers

This "problem" is documented on SharedPreferences.getStringSet.

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

That is ok, but the problem comes when you try to store it: Android compares the modified HashSet that you are trying to save using SharedPreferences.Editor.putStringSet with the current one stored on the SharedPreference, and both are the same object!!!

A possible solution is to make a copy of the Set<String> returned by the SharedPreferences object:

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

That makes s a different object, and the strings added to s will not be added to the set stored inside the SharedPreferences.

Other workaround that will work is to use the same SharedPreferences.Editor transaction to store another simpler preference (like an integer or boolean), the only thing you need is to force that the stored value are different on each transaction (for example, you could store the string set size).

like image 63
JoseLSegura Avatar answered Sep 17 '22 12:09

JoseLSegura