安卓SharedPreferences更新无效

6

我知道这个问题在许多帖子中都有解决,但我无法弄清楚这一个。 所以我设置了一个共享偏好,就像这样:

SharedPreferences prefs = MainActivity.this.getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putStringSet(spinnerName, myValueSet  );
editor.apply();

我这样读取偏好设置:

SharedPreferences prefs = MainActivity.this.getPreferences(MODE_PRIVATE);
Set<String> spinnerValuesSet = null;
spinnerValuesSet = prefs.getStringSet(spinnerName,null );

除了在此活动运行时我的更改可见之外,一切都正常,即 - 我显示来自SharedPreferences的值,允许用户删除或添加,然后更新ListView。这有效,但是在重新启动应用程序后,我会获得初始值。 例如,这是我从列表中删除一个值、更新SharedPreferences中的值并更新ListView的方法:

Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
    SharedPreferences prefs =  MainActivity.this.getPreferences(MODE_PRIVATE);
    Set<String> spinnerValuesSet = prefs.getStringSet(spinnerName,null );
    for (String s : spinnerValuesSet)
    {
         if(s == currentSelectedItemString)
         {
             spinnerValuesSet.remove(s);
             SharedPreferences.Editor editor = prefs.edit();
             editor.putStringSet(spinnerName, spinnerValuesSet );
                 editor.apply();
             break;
         }
    }
 updateListValues();

}
});

以下是更新ListView的方法:

 private void updateListValues()
 {
   SharedPreferences prefs = MainActivity.this.getPreferences(MODE_PRIVATE);
   Set<String> spinnerValuesSet = prefs.getStringSet(spinnerName,null );
   if(spinnerValuesSet.size() > 0) 
    {
        names = new ArrayList<String>();
        names.clear();
        int k=0;
        for (String s : spinnerValuesSet) {
             names.add(k, s);
             k++;
        }
        namesAA = new ArrayAdapter<String> (  this, android.R.layout.simple_list_item_activated_1, names );
        myList.setAdapter(namesAA);
   }

非常感谢您的帮助。

任何帮助都非常欢迎。


你尝试使用commit()而不是apply()了吗?apply()在保存期间不会告诉你是否有任何错误,也许它没有正常工作。 - jbihan
boolean b = editor.commit(); b - 返回 true。顺便说一句,由于使用了相同的 getPreferences 方法成功更新了 ListView,我认为提交确实有效。第一个值是如何被存储和永远不被覆盖的呢?(我针对 API 17 并在 Nexus 7 上进行测试) - AndyZ
5个回答

9

SharedPreferences的各种get方法返回的对象应被视为不可变的。请参考SharedPreferences类概述

您必须通过SharedPreferences.edit()返回的SharedPreferences.Editor调用remove(String),而不是直接在SharedPreferences.getStringSet(String, Set<String>)返回的Set上进行操作。

每次更新内容时,您需要构建一个包含更新后内容的新字符串集合,因为当您想要更新其内容时,必须从SharedPreferences中删除Set条目。


非常感谢。这真的是问题所在。我在每次更改时添加了editor.remove(spinerName); editor.apply();,现在值也会在应用程序关闭后保留。现在,正如您指出的那样,我看到了关于应用程序不可变性的声明。我认为它应该在文档中更突出地标记,因为更改在应用程序运行时生效。 - AndyZ

3
问题出现在SharedPreference返回的Set是不可变的。https://code.google.com/p/android/issues/detail?id=27801 我通过创建一个新的Set实例并将从SharedPreferences返回的所有值存储在其中来解决这个问题。
     //Set<String> address_ids = ids from Shared Preferences...

  //Create a new instance and store everything there.
        Set<String> all_address_ids = new HashSet<String>();
        all_address_ids.addAll(address_ids);

现在使用新实例将更新推回到SharedPreferences中。

0

使用 editor.commit(); 代替 editor.apply();

示例代码:

SharedPreferences prefs = MainActivity.this.getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putStringSet(spinnerName, myValueSet  );
editor.commit();


希望这能有所帮助。


3
提交(Commit)和应用(Apply)基本上是相同的操作,但应用是异步的,并且不会出现任何提交失败。(同时仅在API 9及以上版本可用。) - Jacob Malliet

0

根据操作系统版本的不同,您可能需要以不同的方式保存值。

boolean apply = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;

public static void saveValue(SharedPreferences.Editor editor)
{
    if(apply) {
        editor.apply();
    } else {
        editor.commit();
    }
}

谢谢,我忘了提到,我针对API 17并在Nexus 7上进行测试,这不应该是一个问题。 - AndyZ

0
我可能错了,但我认为您检索共享首选项的方式有问题。请尝试使用
SharedPreferences prefs = getSharedPreferences("appPreferenceKey", Context.Mode_Private);

但是 getPreferences() 的文档说:检索一个 SharedPreferences 对象,用于访问此活动私有的首选项。这只是通过将此活动的类名作为首选项名称传递给底层的 getSharedPreferences(String, int) 方法来调用它。 - AndyZ
更改为getSharedPreferences(“myprefKey”,MODE_PRIVATE);,但它显示与以前相同的行为。在运行活动时更新值,在应用程序关闭和重新启动时会给出默认值。 - AndyZ

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