37

我在共享首选项中保存了一个字符串集,如果我读出它就可以了。我开始其他活动,回去再读一遍,就可以了。如果我关闭应用程序并重新启动它,我会得到集合,但只有 1 个项目而不是 4 个项目。它一直在发生。有已知问题吗?我能做错什么?

在一个类中,在应用程序的 oncreate 方法中创建的内容有一个 SharedPreferences 和一个 SharePreferences.Editor 变量。我在保存和加载方法中使用它们。

public void saveFeedback(FeedbackItem feedbackItem) {
    checkSp();
    Set<String> feedbackSet = getFeedbacksSet();
    if(feedbackSet == null){
        feedbackSet = new HashSet<String>();
    }
    JSONObject json = createJSONObjectfromFeedback(feedbackItem);
    feedbackSet.add(json.toString());
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, feedbackSet);
    ed.commit();
}

public Set<String> getFeedbacksSet(){
    checkSp();
    Set<String> ret = sp.getStringSet(CoreSetup.KEY_FEEDBACK, null);
    return ret;
}

private void checkSp(){
    if(this.sp == null)
        this.sp = applicationContext.getSharedPreferences(applicationContext.getPackageName(), Context.MODE_PRIVATE);
    if(this.ed == null)
        this.ed = this.sp.edit();
}

我只是不明白这是怎么发生的,在应用程序运行时完美地存储所有项目,然后在重新启动后并非所有项目都在集合中。而且我认为,如果所有项目都被移除,那么它可能比一些项目消失更容易接受,而一个项目仍然存在。有解释吗?

4

7 回答 7

29

根据您的问题,您应该仅在将 4 个项目添加到集合后才调用 commit。在您的代码中,您正在为每个反馈调用 commit,这将覆盖以前的反馈。

更新: http: //developer.android.com/reference/android/content/SharedPreferences.html#getStringSet (java.lang.String , java.util.Set)

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.

这正是你正在做的

于 2013-11-13T09:19:04.163 回答
20

这个“问题”记录在 SharedPreferences.getStringSet().

getStringSet() 返回 SharedPreferences 中存储的 HashSet 对象的引用。当您向该对象添加元素时,它们实际上是SharedPreferences 中添加的。

解决方法是复制返回的 Set 并将新 Set 放入 SharedPreferences。我测试了它并且它有效。

在 Kotlin 中,这将是

    val setFromSharedPreferences = sharedPreferences.getStringSet("key", mutableSetOf())
    val copyOfSet = setFromSharedPreferences.toMutableSet()
    copyOfSet.add(addedString)

    val editor = sharedPreferences.edit()
    editor.putStringSet("key", copyOfSet)
    editor.apply() // or commit() if really needed
于 2014-01-07T09:43:26.200 回答
8

尝试创建您的集合的副本,然后您可以将其保存在相同的首选项中:

private Set<String> _setFromPrefs;


public void GetSetFromPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    Set<String> someSets = sharedPref.getStringSet("some_sets", new HashSet<String>() );
    _setFromPrefs = new HashSet<>(someSets); // THIS LINE CREATE A COPY
}


public void SaveSetsInPrefs()
{
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putStringSet("some_sets", _setFromPrefs);
    editor.commit();
}
于 2017-03-01T19:34:06.727 回答
1

遇到同样的问题。通过在实例化之后和提交之前清除编辑器来解决它。

sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    sFavList = sPrefs.getStringSet(context.getResources().getString(R.string.pref_fav_key), null);
    sEditor = sPrefs.edit();
    sEditor.clear(); // added clear, now Set data persists as expected
    if (sFavList == null) sFavList = new HashSet<>();
    sFavList.add(title);
    sEditor.putStringSet(context.getResources().getString(R.string.pref_fav_key), sFavList).apply();

我尝试按照其他人的建议创建副本,但这对我不起作用。

在这里找到了这个解决方案。

于 2017-10-20T14:03:36.740 回答
0

根据该文件,SharedPreferences 中的字符串集应该被视为不可变的,当试图修改它时,事情会变得很糟糕。解决方法是:获取现有集,制作副本,更新副本,然后将其保存回共享首选项,就像它是新集一样。

Set<String> feedbackSet = getFeedbacksSet();
if(feedbackSet == null){
    feedbackSet = new HashSet<String>();
}

//make a copy of the set, update the copy and save the copy
Set<String> newFeedbackSet = new HashSet<String>();
JSONObject json = createJSONObjectfromFeedback(feedbackItem);
newFeedbackSet.add(json.toString());
newFeedbackSet.addAll(feedbackSet);
ed.putStringSet(CoreSetup.KEY_FEEDBACK, newFeedbackSet);
ed.commit();
于 2016-11-18T01:34:44.697 回答
0
public void saveFeedback(FeedbackItem feedbackItem) {
    checkSp();
    Set<String> feedbackSet = getFeedbacksSet();
    if(feedbackSet == null){
        feedbackSet = new HashSet<String>();
    }
    JSONObject json = createJSONObjectfromFeedback(feedbackItem);
    feedbackSet.add(json.toString());
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, null);
    ed.commit();
    ed.putStringSet(CoreSetup.KEY_FEEDBACK, feedbackSet);
    ed.commit();
}
于 2021-07-11T18:36:05.027 回答
-1

在 sharedpreferences 中保存字符串

   SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
   editor.putString("text", mSaved.getText().toString());
   editor.commit();

从共享首选项中检索数据

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 String restoredText = prefs.getString("text", null);
于 2013-11-13T08:53:11.833 回答