在Android SharedPreferences中,Set<String>在强制关闭时无法保存

23

我正在尝试使用Android的SharedPreferences,我已经记录了所有内容,下面的代码确实提交了字符串集合。问题是当我强制关闭应用程序并重新启动时,settings.getStringSet返回一个空集合。没有任何错误消息。

我已经尝试使用PreferenceManager.getDefaultSharedPreferences,但对我也不起作用。

感谢你的时间。

public static final String PREFS_NAME = "MyPrefsFile";
private static final String FOLLOWED_ROUTES = "followedRoutes";

并且在调用saved时:

public void onFollowClicked(View view){

SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();

Set<String> follows =  settings.getStringSet(FOLLOWED_ROUTES, new HashSet<String>());
follows.add(routeId);

editor.putStringSet(FOLLOWED_ROUTES, follows);
editor.commit();

}

1
你尊重生命周期吗?你在哪个状态下保存数据? - Steve Benett
一切都在我强制退出之前保存了。问题是,settings.getStringSet(…不返回我提交的值。我还尝试将commit()替换为apply()-但没有成功。 - Malin
2个回答

35

你也可以按照g00dy提到的方法解决这个bug:

从sharedPreferences中获取集合并保存在一个变量中。

然后,在保存时先删除sharedPreferences中的集合,再重新添加它。

SharedPreferences.Editor editor= sharedPref.edit();
editor.remove("mSet");
editor.apply(); 
editor.putStringSet("mSet", mSet);
editor.apply();

确保使用apply()或commit()两次。

或者,如果您在使用Kotlin编写代码,只需:

PreferenceManager.getDefaultSharedPreferences(applicationContext)
    .edit {
        this.remove("mSet")
        this.apply()
        this.putStringSet("mSet", mSet)
    }

9
这救了我的命,但希望有更详细的说明文档。 - Caio Vertematti
非常感谢,我以为我要疯了。Android请修复这个问题,或者至少记录一下它是一个问题!谢谢。 - JamisonMan111
哇塞,太棒了!我已经开始放弃了。 - Natesh bhat
必须接受答案。这拯救了我的一天!谢谢! - duyhungws

22

在这里查看:这里

另外还有参考:

SharedPreferences

SharedPreferences.Editor

编辑:

实际上这里存在一个错误,请查看这里。其中的摘录如下:

此问题仍然存在于API级别17中。

它是由于SharedPreferences类的getStringSet()方法不返回Set对象的副本而引起的:它返回整个对象,并且当您向其添加新元素时,SharedPrefencesImpl.EditorImpl类的commitToMemory方法会查看现有值是否等于之前存储的值。

解决此问题的方法是复制SharedPreferences.getStringSet返回的Set或使用始终更改的其他偏好强制写入内存(例如,每次存储集合大小的属性)

编辑2:

可能有一个解决方案在这里,看一看。


1
无法实例化类型Set<String>,因为set只是一个接口。 - Malin
如果我使用字符串,它可以正常工作,但如果我使用stringSet,它就不行了,而这正是我所需要的。我也尝试过: HashSet<String> follows = (HashSet<String>) settings.getStringSet(FOLLOWED_ROUTES, new HashSet<String>()); - Malin
我编辑了我的回复。这种用法存在一个错误,他们提供了一种解决方法,或者说是类似的方法。 - g00dy
1
解决方案,如您在此链接(https://dev59.com/VGs05IYBdhLWcg3wPfgR)中提供的,有效!正如您所说,这是一个错误。SharedPreferences的getStringSet()方法不会返回Set对象的副本。使用JSONArray与getString()相结合是我解决问题的方法。 - Malin
你的答案是正确的。我曾试图将Set<String>保存在SharedPrefrences中,但它根本没有保存或者在一段时间后才保存,并且不是立即保存 - 尽管使用了sharedPreferences.edit().putStringSet("favs", set).commit();。最终我没有保存“set”,而是保存了set = new HashSet<>(set);,这解决了问题。 - kosiara - Bartosz Kosarzycki
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接