我遇到一个奇怪的问题,即在返回应用程序时没有更新SharedPreferences。这是场景:
我有两个使用相同共享首选项的项目。 Project1和Project2。它们是独立但相关的应用程序。它们使用相同的密钥签名,并使用sharedUserId来共享信息。
Project1打开Project2。
Project2检索SharedPreferences文件并通过以下方法写入:
Context prefsContext = c.createPackageContext(packageNameOfProject1, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences prefs = prefsContext.getSharedPreferences(fileName, Context.MODE_PRIVATE);
SharedPreferences.editor editor = prefs.edit();
editor.putBool("bool1", value1);
editor.putBool("bool2", value2);
...
editor.putBool("boolN", valueN);
editor.apply();
完成后,我通过调用finish()
返回Project1。
Project1然后读取数据:
SharedPreferences prefs = getSharedPreferences(getPreferencesFileName(), Context.MODE_PRIVATE);
Boolean value1 = prefs.getBoolean(fileName, false);
Boolean value2 = prefs.getBoolean(fileName, false);
...
Boolean valueN = prefs.getBoolean(fileName, false);
Map<String, ?> mappings = prefs.getAll();
Set<String> keys = mappings.keySet();
for(String key : keys) {
log.d(TAG, "_____");
log.d(TAG, "Key = " + key);
log.d(TAG, "Value = " + mappings.get(key));
}
问题是Project1中的值未更新。我可以根据最后的日志告诉文件甚至不生成映射。但是,我可以验证xml是否正在更新。如果我强制停止应用程序然后重新启动它,Project1中的所有映射都在那里。所有的值都是正确的。但是,当用户离开Project2时,我需要更新它们。我觉得这里有一些我不知道但却找不到的东西。
我在这个问题上唯一能找到的是:
SharedPreferences.Editor not being updated after initial commit
SharedPreferences value is not updated
这些没有用,因为我已经这样做了。
我在两个清单中都设置了WRITE_EXTERNAL_STORAGE。 fileName是相同的(否则当我重新进入应用程序时我将无法读取该文件)。
编辑:
我应该注意到我确实尝试editor.commit()
而不是editor.apply()
因为我认为我正面临着竞争条件。问题仍然存在。我想由于某种原因,使用Project1中的SharedPreference的旧引用而不是新的引用,即使我每次都懒得加载它。
EDIT2:
好的,进一步测试看看id是怎么回事。我决定尝试相反的方向。
在Project1中我做:
Float testFloat (float) Math.random();
Log.d("TEST_FLOAT", "Project1: TEST_FLOAT = " + testFloat);
prefs.edit().putFloat("TEST_FLOAT", testFloat).commit();
在Project2中我做:
Log.d("TEST_FLOAT", "Project2: TEST_FLOAT = " + prefs.getFloat("TEST_FLOAT", 0.0f));
然后我在两者之间来回走动:Project1->Project2->Project1->Project2->Project1->Project2
这里是logcat的结果:
Project1: TEST_FLOAT = 0.30341884
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.89398974
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.81929415
Project2: TEST_FLOAT = 0.30341884
换句话说,它正在读取和写入同一个文件。但是,它保留了在项目中首次打开它时所具有的映射。即使我关闭了项目,映射仍然存在,直到应用程序被强制停止。
答案 0 :(得分:19)
最终答案:
替换
getSharedPreferences(fileName, Context.MODE_PRIVATE);
与
getSharedPreferences(fileName, Context.MODE_MULTI_PROCESS);
根据文件:
Context.MODE_MULTI_PROCESS
SharedPreferences loading flag:设置后,磁盘上的文件将是 即使共享首选项实例是,也检查了修改 已加载此过程。有时需要这种行为 应用程序有多个进程的情况,都写入 相同的SharedPreferences文件。一般来说有更好的形式 但是,流程之间的沟通。
这是之前和之前的遗留(但未记录)行为 姜饼(Android 2.3)和此标志在定位时隐含 这样的发布。对于针对大于的SDK版本的应用程序 Android 2.3(Gingerbread),如果需要,必须明确设置此标志。
我知道这有一个简单的疏忽。
答案 1 :(得分:1)
尝试拨打editor.commit();
而不是editor.apply();
。通常他们也应该这样做,但我注意到有时会出现一些奇怪的行为。
答案 2 :(得分:1)
在SharedPreferences文档中,方法“apply()”异步(延迟)写入文件,方法“commit()”将信息同步(立即)写入文件。
同样从文档中,他们说您在使用上述任何方法时都不需要担心活动生命周期,因为它们确保在状态更改之前完成“apply()”写入,如果它们是在同一系统进程中运行。
但是,当您使用两个不同的项目时,它们运行在两个不同的进程中,您无法确定项目2上的“apply()”将在“onResume()”在项目1上启动之前结束。
我建议你尝试“commit()”而不是“apply()”来强制同步写入。如果这不能解决问题,您可以在读取项目1中的首选项之前添加几秒钟的延迟,只是为了检查问题是否与此延迟写入有关。
- 编辑 -
要调试此问题,请执行以下操作:
1-In Eclipse选择/添加视图“文件资源管理器”并导航到目录:
/ data / data / [您的包名] / shared_prefs
您的包名应该类似于“com.myproject.shared”
2 - 选择包含已保存首选项的文件,然后按“下载到PC”按钮。
3 - 检查文件内容是否符合您的期望。
祝你好运。