尝试存储使用SharedPreferences的string集时的错误行为
我试图使用SharedPreferences
API来存储一组string。
Set<String> s = sharedPrefs.getStringSet("key", new HashSet<String>()); s.add(new_element); SharedPreferences.Editor editor = sharedPrefs.edit(); editor.putString(s); edit.commit()
当我第一次执行上面的代码时, s
被设置为默认值(刚刚创build的最后一个空的HashSet
),并且存储没有问题。
第二次和下一次我执行这个代码, s
对象返回第一个元素添加。 我可以添加元素,并且在程序执行期间显然存储在SharedPreferences
,但是当程序被SharedPreferences
时, SharedPreferences
从其持久性存储中再次读取,并且新值丢失。
第二个和之后的元素怎么能被存储起来,这样他们就不会迷路了?
SharedPreferences.getStringSet
logging了这个“问题”。
SharedPreferences.getStringSet
返回SharedPreferences.getStringSet
中存储的HashSet对象的引用。 向这个对象添加元素时,它们实际上被添加到SharedPreferences
。
这是好的,但是当你尝试存储它时,问题就出现了:Android将使用SharedPreferences.Editor.putStringSet
修改的HashSet与SharedPreferences.Editor.putStringSet
存储的当前的HashSet进行比较,并且它们是同一个对象!
一个可能的解决scheme是复制由SharedPreferences
对象返回的Set<String>
:
Set<String> s = new HashSet<String>(sharedPrefs.getStringSet("key", new HashSet<String>()));
这是一个不同的对象,添加到s
的string将不会被添加到SharedPreferences
存储的集合中。
其他解决方法是使用相同的SharedPreferences.Editor
事务来存储另一个更简单的首选项(如整数或布尔值),唯一需要的是强制每个事务的存储值不同(例如,您可以存储string集大小)。
这种行为是通过devise来logging的:
来自getStringSet:
“请注意,你不能修改这个调用返回的set实例,如果你这样做的话,存储的数据的一致性是不能保证的,你根本不能修改这个实例。
而且这似乎是相当合理的,尤其是如果它在API中logging,否则这个API将不得不复制每个访问。 所以这个devise的原因可能是性能。 我想他们应该把这个函数的返回结果封装在不可修改的类实例中,但是这又一次需要分配。
正在为相同的问题寻找解决scheme,通过以下解决scheme:
1)从共享首选项中检索现有的集合
2)制作一个副本
3)更新副本
4)保存副本
SharedPreferences.Editor editor = sharedPrefs.edit(); Set<String> oldSet = sharedPrefs.getStringSet("key", new HashSet<String>()); //make a copy, update it and save it Set<String> newStrSet = new HashSet<String>(); newStrSet.add(new_element); newStrSet.addAll(oldSet); editor.putStringSet("key",newStrSet); edit.commit();
为什么
我尝试了所有上述的答案没有为我工作。 所以我做了以下步骤
- 在将新元素添加到旧的共享pref列表中之前,请将其复制一份
- 调用上述副本的方法作为该方法的参数。
- 在那个方法里面清除拥有这个值的共享前缀。
-
将副本中存在的值添加到已清除的共享首选项,将其视为新的。
public static void addCalcsToSharedPrefSet(Context ctx,Set<String> favoriteCalcList) { ctx.getSharedPreferences(FAV_PREFERENCES, 0).edit().clear().commit(); SharedPreferences sharedpreferences = ctx.getSharedPreferences(FAV_PREFERENCES, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putStringSet(FAV_CALC_NAME, favoriteCalcList); editor.apply(); }
我正面临的问题,值不是持久的,如果我从后台清理应用程序后重新打开应用程序只有第一个元素添加到列表中显示。