我多次使用共享偏好设置,但出于某种原因,我正在测试的新应用中没有保存更改。以下是重要代码的片段:
SharedPreferences sp = getSharedPreferences(getString(R.string.key_preferences), MODE_PRIVATE);
Set<String> widgets = sp.getStringSet(getString(R.string.key_widgets), (new HashSet<String>()));
widgets.add(name + " " + Integer.toString(appWidgetId) + " " + address);
sp.edit().putStringSet(getString(R.string.key_widgets), widgets).commit();
我已经使用日志来检查小部件是否已添加到集合中,但是从未保存更新的集合。如果我将最后一行更改为...
sp.edit().putStringSet(getString(R.string.key_widgets), widgets).putString("testkey", "testvalue").commit();
...然后一切都保存得很好。我错过了什么?
*更新:
我发现这也有效:
SharedPreferences sp = getSharedPreferences(getString(R.string.key_preferences), MODE_PRIVATE);
Set<String> widgets = sp.getStringSet(getString(R.string.key_widgets), (new HashSet<String>()));
Set<String> newWidgets = new HashSet<String>();
for (String widget : widgets) newWidgets.add(widget);
newWidgets.add(name + " " + Integer.toString(appWidgetId) + " " + address);
sp.edit().putStringSet(getString(R.string.key_widgets), newWidgets).commit();
也许我在文档中遗漏了一些关于需要为编辑器创建新对象以保存prefs的内容。
*更新2:
如果我创建一个编辑器对象没有区别:
SharePreferences.Editor spe = sp.edit();
spe.putStringSet(getString(R.string.key_widgets), widgets)
spe.commit();
答案 0 :(得分:13)
我们只需要更仔细地阅读文档
请注意,您不得修改此调用返回的set实例。如果您这样做,则无法保证存储数据的一致性,也无法根据您的能力修改实例。
事实上,应该在 SharedPreferences.Editor 中注意不要发送 putStringSet 之后可能会修改的集合。在修改之前复制从 getStringSet 返回的集合,并在将集合发送到putStringSet之前复制集合。
SharedPreferences myPrefs = getSharedPreferences(myPrefName, MODE_PRIVATE);
HashSet<String> mySet = new HashSet<string>(myPrefs.getStringSet(mySetKey, new HashSet<string()));
....
SharedPreferences.Editor myEditor = myPrefs.edit();
然后其中一个
myEditor.putStringSet(mySetKey, new HashSet<String>(mySet));
或
myEditor.putStringSet(mySetKey, (Set<String>) mySet.clone());
答案 1 :(得分:7)
我想稍微改善Chike的答案。
如果我们查看implementation(自v4.0.1以来未更改),首先提交内存然后再提交内存, commit()没有保存到磁盘的原因是显而易见的等待磁盘写入完成:
public boolean commit() {
MemoryCommitResult mcr = commitToMemory();
SharedPreferencesImpl.this.enqueueDiskWrite(
mcr, null /* sync write on this thread okay */);
try {
mcr.writtenToDiskLatch.await();
} catch (InterruptedException e) {
return false;
}
notifyListeners(mcr);
return mcr.writeToDiskResult;
}
关键是,如果我们使用 getStringSet()中的相同实例调用 putStringSet(),则不会检测到任何更改:
// Returns true if any changes were made
private MemoryCommitResult commitToMemory() {
MemoryCommitResult mcr = new MemoryCommitResult();
...
for (Map.Entry<String, Object> e : mModified.entrySet()) {
String k = e.getKey();
Object v = e.getValue();
...
if (mMap.containsKey(k)) {
Object existingValue = mMap.get(k);
if (existingValue != null && existingValue.equals(v)) {
continue;
}
}
mMap.put(k, v);
}
mcr.changesMade = true;
...
}
...
}
}
return mcr;
}
由于没有进行任何更改, writeToFile()很乐意跳过磁盘写入并设置成功标志:
private void writeToFile(MemoryCommitResult mcr) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
if (!mcr.changesMade) {
// If the file already exists, but no changes were
// made to the underlying map, it's wasteful to
// re-write the file. Return as if we wrote it
// out.
mcr.setDiskWriteResult(true);
return;
}
...
}
...
}
请参阅Chike的答案,在将字符集保存到同一个SharedPreference键之前复制字符串集。
答案 2 :(得分:1)
您需要保存Editor对象,然后调用commit()(在Android 2.3之前)或apply()(对于Android 2.3及更高版本)。
SharedPreferences.Editor editor = sp.edit();
editor.put...
editor.commit();
答案 3 :(得分:1)
我遇到了你描述的同样问题。
我的布尔和字符串首选项存储没有问题,但当我尝试存储字符串集时,问题就开始了。
当我将第一个元素添加到字符串集并存储它时,它可以工作。但是,当我尝试添加第二个时,它会被添加到内存中(我可以刷新一个显示该首选项中存储的所有元素的视图)。如果我强制关闭我的应用程序并再次重新启动它,共享首选项只会添加第一个元素。
我调试了我的代码并看到我添加新代码时存储字符串的HashSet是可以的,但更改不会写入持久存储
答案 4 :(得分:0)
对共享首选项使用以下结构:
<强> 1。创建对象
SharedPreferences myPrefs = context.getSharedPreferences(PREF_NAME, MODE_WORLD_READABLE);
<强> 2。要在共享首选项中保存值:
为共享首选项创建编辑器:
SharedPreferences.Editor prefsEditor = myPrefs .edit();
然后将值放入编辑器:
prefsEditor.putString("KEY", VALUE);
现在提交更改以保存共享首选项:
prefsEditor.commit();
答案 5 :(得分:0)
我将以下代码放入onCreate方法中,因此每次我重新启动应用程序时它将重置。
preferences.edit().putInt(...).apply();
使用此处所述的方法代替:https://stackoverflow.com/a/28789934/11266070
SharedPreferences sharedPrefs = getSharedPreferences("sp_name", MODE_PRIVATE);
SharedPreferences.Editor ed;
if(!sharedPrefs.contains("initialized")){
ed = sharedPrefs.edit();
//Indicate that the default shared prefs have been set
ed.putBoolean("initialized", true);
//Set some default shared pref
ed.putString("myDefString", "wowsaBowsa");
ed.commit();
}
希望这会提醒某人...