简体   繁体   English

Android SharedPreferences String Set - 应用程序重启后删除了一些项目

[英]Android SharedPreferences String Set - some items are removed after app restart

I save a string set in the shared preferences, if I read it out it's ok. 我在共享首选项中保存了一个字符串集,如果我读出来就可以了。 I start other activities, go back and read it again, it's ok. 我开始其他活动,回去再读一遍,没关系。 If I close the application, and start it again, I get the set, but with only 1 item instead of 4. It happens all the time. 如果我关闭应用程序,然后重新启动它,我会得到设置,但只有1项而不是4项。它始终发生。 Is there a known issue? 有一个已知的问题吗? What could I do wrong? 我该怎么办?

In a class, what is created in the application's oncreate method I have a SharedPreferences and a SharePreferences.Editor variable. 在类中,在应用程序的oncreate方法中创建的内容我有一个SharedPreferences和一个SharePreferences.Editor变量。 I use them in the save and load methods. 我在保存和加载方法中使用它们。

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();
}

I just can't understand how could it happen, to store perfectly all items while the app is running, then after a restart not all items are in the set. 我只是无法理解怎么可能发生,在应用程序运行时完美存储所有项目,然后在重新启动后并非所有项目都在集合中。 And I think if all items are removed it could be more acceptable than some items are gone, and one item is still there. 而且我认为如果所有物品都被移除,它可能比一些物品消失更可接受,而且还有一件物品。 Is there an explanation? 有解释吗?

Based on your question, you should call commit only after 4 items have been added to the set. 根据您的问题,您应该在将4个项目添加到集合后调用commit。 In your code, you are calling commit for each feedback which will overwrite the previous feedback. 在您的代码中,您为每个反馈调用commit,这将覆盖先前的反馈。

Update : http://developer.android.com/reference/android/content/SharedPreferences.html#getStringSet(java.lang.String , java.util.Set) 更新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.

This is exactly what you are doing 这正是你在做的事情

This "problem" is documented on SharedPreferences.getStringSet() . SharedPreferences.getStringSet()记录了这个“问题”。

getStringSet() returns a reference of the stored HashSet object inside SharedPreferences. getStringSet()返回SharedPreferences中存储的HashSet对象的引用。 When you add elements to this object, they are added in fact inside SharedPreferences. 向此对象添加元素时,它们实际上会添加 SharedPreferences中。

The workaround is making a copy of the returned Set and putting the new Set into SharedPreferences. 解决方法是复制返回的Set并将新Set放入SharedPreferences。 I tested it and it works. 我测试了它,它的工作原理。

In Kotlin, that would be 在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

Try to create Copy of your set, and than you can save it in same prefs: 尝试创建集合的副本,然后将其保存在相同的首选项中:

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();
}

According to the document, the String Set in SharedPreferences should treated as immutable, things go south when trying to modify it. 根据该文档,SharedPreferences中的字符串集应该被视为不可变的,当尝试修改它时,事情就会向南移动。 A work around would be: Get the existing set, make a copy of it, update the copy and then save it back to the shared preferences like it was a new set. 解决方法是:获取现有集,制作副本,更新副本,然后将其保存回共享首选项,就像它是一个新集。

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();

Ran into this same problem. 陷入同样的​​问题。 Solved it by clearing the editor after instantiating and before committing. 通过在实例化之后和提交之前清除编辑器来解决它。

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();

I tried creating a copy as others suggested, but that didn't work for me. 我尝试按照其他人的建议制作副本,但这对我不起作用。

Found this solution here . 在这里找到了解决方案

To save string in sharedprefernces 在sharedprefernce中保存字符串

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

To retrieve data from shared preference 从共享首选项中检索数据

 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 String restoredText = prefs.getString("text", null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM