piu*_*lte 11 android sharedpreferences
我已多次使用共享首选项,但由于某些原因,更改未保存在我正在测试的新应用程序中.这是重要代码的片段:
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();
Run Code Online (Sandbox Code Playgroud)
我已经使用日志来检查小部件是否已添加到集合中,但是从未保存更新的集合.如果我将最后一行更改为...
sp.edit().putStringSet(getString(R.string.key_widgets), widgets).putString("testkey", "testvalue").commit();
Run Code Online (Sandbox Code Playgroud)
...然后一切都很好.我错过了什么?
*更新:
我发现这也有效:
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();
Run Code Online (Sandbox Code Playgroud)
也许我在文档中遗漏了一些关于需要为编辑器创建新对象以保存prefs的内容.
*更新2:
如果我创建一个编辑器对象没有区别:
SharePreferences.Editor spe = sp.edit();
spe.putStringSet(getString(R.string.key_widgets), widgets)
spe.commit();
Run Code Online (Sandbox Code Playgroud)
小智 14
我们只需要更仔细地阅读文档
请注意,您不得修改此调用返回的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();
Run Code Online (Sandbox Code Playgroud)
其中之一
myEditor.putStringSet(mySetKey, new HashSet<String>(mySet));
Run Code Online (Sandbox Code Playgroud)
要么
myEditor.putStringSet(mySetKey, (Set<String>) mySet.clone());
Run Code Online (Sandbox Code Playgroud)
我想改善一下Chike的答案.
之所以提交()没有保存到磁盘是显而易见的,如果我们看一看的实施(因为V4.0.1不变),其承诺的内存,然后再等待磁盘写入完成:
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;
}
Run Code Online (Sandbox Code Playgroud)
关键是,如果我们使用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;
}
Run Code Online (Sandbox Code Playgroud)
由于没有进行任何更改,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;
}
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
请参阅Chike的答案,在将其保存到相同的SharedPreference键之前复制String set.
| 归档时间: |
|
| 查看次数: |
3682 次 |
| 最近记录: |