【问题标题】:Android SharedPreferences update does not workAndroid SharedPreferences 更新不起作用
【发布时间】:2013-09-13 19:33:58
【问题描述】:

我知道,这个问题已经在很多线程中处理过,但我无法弄清楚这个。 所以我设置了一个这样的共享偏好:

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()在保存过程中不会告诉你是否有任何错误,可能是没有正常工作
  • 布尔 b = editor.commit(); b - 说的是真的。顺便说一句,由于 ListView 使用相同的 getPreferences 方法成功更新,我认为提交确实有效。第一个值如何被存储并且永远不会被覆盖......(我以 API 17 为目标并在 Nexus 7 上进行测试)

标签: android sharedpreferences


【解决方案1】:

问题发生是因为 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

【讨论】:

    【解决方案2】:

    SharedPreferences 的各种 get 方法返回的对象应该被视为不可变的。参考SharedPreferences Class Overview

    你必须通过SharedPreferences.edit()返回的SharedPreferences.Editor而不是直接在SharedPreferences.getStringSet(String, Set&lt;String&gt;)返回的Set上调用remove(String)

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

    【讨论】:

    • 非常感谢。这确实是问题所在。我添加了 editor.remove(spinerName); editor.apply();对于每一次更改,现在这些值仍然存在,也是一个应用程序杀手。现在,正如您所指出的,我看到了有关应用程序不可变的声明。我认为应该在文档中更突出地标记它,因为更改会在应用程序运行时生效。
    【解决方案3】:

    我可能错了,但我认为您检索共享首选项的方式是问题所在。尝试使用

    SharedPreferences prefs = getSharedPreferences("appPreferenceKey", Context.Mode_Private);

    【讨论】:

    • 但是 getPreferences() 的文档说:检索一个 SharedPreferences 对象以访问此活动私有的首选项。这只是通过传入此活动的类名作为首选项名称来调用底层的 getSharedPreferences(String, int) 方法。
    • 已更改为 getSharedPreferences("myprefKey",MODE_PRIVATE);,但它显示的行为与以前相同。值在运行 Activity 时更新,在应用关闭并重新启动时,它会提供默认值。
    【解决方案4】:

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

    示例代码:

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


    我希望这会有所帮助。

    【讨论】:

    • Commit 和 Apply 做几乎相同的事情。 Apply 只是异步的,没有任何提交失败。 (也仅适用于 api 9+)
    【解决方案5】:

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

    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 上进行测试,这应该不是问题。
    猜你喜欢
    • 2016-12-03
    • 2016-10-11
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多