A little while ago an Android project I’m working was seeing infrequent but regular
ConcurrentModificationError crashes and we were at a loss to reproduce and fix the issue.
It turns out that we were making a common but subtle mistake using
SharedPreference.getStringSet(). We were operating on the returned
Set object: in our case we would be filtering this
Set before saving it again.
The issue is that according to the documentation you shouldn’t ever modify this returned
public abstract Set
getStringSet (String key, Set defValues)
Added in API level 11 Retrieve a set of String values from the preferences.
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.
As a result under certain conditions or perhaps on certain Android implementation we were getting
ConcurrentModifictionError crashes when users were changing their app settings.
The fix was simple enough. Just make a new copy of the
Set before you operate on it.
String key = "string_set_key"; PreferenceManager m = PreferenceManager.getDefaultSharedPreferences(context); Set<String> string_set = m.getStringSet(key, new HashSet<>()); // Make a new copy before we operate Set<String> string_set_copy = new HashSet<String>(string_set); // Now we can safely modifiy the set string_set_copy.add("first_value"); string_set_copy.remove("second_value") // Now we can save these changes SharedPreferences.Editor editor = m.edit(); editor.putStringSet(key, string_set_copy); editor.apply();