我目前正在使用SharedPreferences来跟踪在通过AlarmManager启动的BroadcastReceiver中执行工作的项目列表。除特定场景外,一切都很有效。当我触发一个新项目来执行工作时,让它完成工作,然后删除该项目(所有这些都通过SharedPreferences编辑),它在应用程序运行时可以很好地工作。当列表中没有任何内容并且我打开任务管理器并终止应用程序时,突然该项目出现在BroadcastReceiver中(在应用程序关闭后仍然运行)。是什么导致这种行为?我应该在应用程序退出时杀死所有接收器吗?当Receiver仍在运行时,Activity是否会关闭默认值返回另一个SharedPreferences对象?
从SharedPreferences对象添加/删除项目的代码
final SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME,
Context.MODE_PRIVATE);
final Editor editor = prefs.edit();
mUpdates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, new HashSet<String>());
if (!mUpdates.contains(key)) {
mUpdates.add(key);
} else {
mUpdates.remove(key);
}
editor.putStringSet(Config.PREFS_KEY_ACTIVE_TASKS, mUpdates);
editor.apply();
广播接收者代码
public void onReceive(Context context, Intent intent) {
SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME, Context.MODE_PRIVATE);
if(prefs.contains(Config.PREFS_KEY_ACTIVE_TASKS)) {
Set<String> updates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, null);
if(updates != null) {
Log.d("RECEIVER","Size="+updates.size());
for(String key : updates) {
EntityChangeManager.notifyListeners(key);
}
}
}
}
当我运行代码来添加/删除初始列表中的对象时,正如预期的那样,我看到了
04-30 20:04:44.165: D/RECEIVER(27079): Size=1
04-30 20:04:44.165: D/RECEIVER(27079): Size=0
当我杀死应用程序时,我看到了
04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapUtilization:0.25
04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapIdealFree:8388608
04-30 20:04:43.254: D/ActivityThread(27079): setTargetHeapConcurrentStart:2097152
04-30 20:04:43.264: D/RECEIVER(27079): Size=1
兴趣点:
答案 0 :(得分:2)
将editor.apply();
更改为editor.commit()
。杀死应用程序时,可能无法将更改写入磁盘。来自http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()
与commit()同步地将其首选项写入持久存储,apply()会立即将其更改提交到内存中的SharedPreferences,但会启动异步提交到磁盘,并且不会通知您任何失败。如果此SharedPreferences上的另一个编辑器在apply()尚未完成时执行常规commit(),则commit()将阻塞,直到完成所有异步提交以及提交本身。
答案 1 :(得分:1)
如果使用StringSet遇到任何细微差别,解决方案是将另一个属性与StringSet本身一起写入SharedPreferences对象(如StringSet.size())。原因是SharedPreferences库仅将对象与存储对象进行比较,添加/删除数据不一定会导致对象本身发生更改,因此看起来好像没有差异。
可以检查对象的大小,如果在编辑对象时它是0,而不是编辑它,只需将对象设置为null,然后再将其保存到SharedPreferences。我选择了第二个sharedpref设置,从那以后工作正常。
答案 2 :(得分:1)
即使这是一个相对陈旧的问题,我偶然发现了同样的问题。如果将来参考,这可能是有用的。
问题:从BroadcastReceiver检索的旧值。这是由于没有更新StringSet内容的SharedPreferences引起的,因为它是同一个对象。
以下内容已更改为通过SharedPreferences提供持久存储(我不知道哪些因素对解决方案有所帮助):
android:process=":remote"
,必须删除。Context.MODE_MULTI_PROCESS
)context.getSharedPreferences(ref,Context.MODE_MULTI_PROCESS)
作为模式
null
值解决了我的问题: editor.putStringSet(ref,null);
editor.commit();
editor.putStringSet(ref, valuesToBeStored);
我不知道是否需要前两次更改。