在我的应用中,我将一些数据存储在SharedPreferences
中 - 它可以根据需要运行。
现在我想为某些不正确的情况创建日志消息。
我成功处理了首选项为空或在加载时抛出异常的情况。
保存值时唯一可以显示的错误是commit()
返回false
- 我不知道为什么会发生这种情况以及在这种情况下应该做些什么。
所以我的问题是:
commit()
方法何时返回false
?
在那种情况下我该怎么办?
一个可能的解决方案是一次又一次地呼叫commit()
(类似while (!editor.commit()) {}
)吗?
答案 0 :(得分:11)
虽然(!editor.commit()){;}可以成为成功的解决方案吗?
'commit'操作是同步的并且在UI线程上执行,因此,如果每次尝试执行commit
时都会发生一些不可恢复的错误,那么您将使用此代码阻止整个UI线程,用户将看到ANR。不好。
另一方面,'apply'是异步的,因此即使你将无限期地执行它,它也无法阻止UI线程。
文档对“提交”操作可能失败的说法很少(请查看here,here和there)。首选项存储在存储在内部存储器中的xml文件中,因此可能的一个失败可能是损坏的xml文件。第二个可以在documentation中找到:
请注意,当两个编辑者同时修改首选项时 时间,最后一个调用commit wins。
关于损坏的文件几乎无法做到,而且,不要尝试同时修改来自不同位置的首选项。 :)
答案 1 :(得分:11)
首先,你永远不想做:
while(!editor.commit()) {;}
。如果你想重试一次提交,你会做几次,而不是永远循环。
关于commit()何时返回-1: commit()和apply()都会对内存进行更改,然后进行调用以将更改写入磁盘(per source)。 commit()等待磁盘写入返回以返回结果。因此,您的问题的答案是:“将偏好状态保存到磁盘时,您的特定commit()调用将失败。”由于更改反映在内存中,因此在您尝试写入磁盘之前或之后,可能会或可能不会通过另一个commit()或apply()调用将其写入磁盘(想想赛车线程)。由于没有代码可以回滚内存更新而SharedPreferences是单例(per source),即使应用中的其他组件没有保存到磁盘,它们也会看到您的更改。
总之,循环几次(不是永远)以确保提交()写入磁盘似乎很好,让你通过一个间歇性的I / O问题,但它将是一个罕见的基于I / O的情况,它失败。如果您需要完美的提交范围,您可能需要重新读取磁盘以验证每个commit()调用,这些调用具有性能影响并且除了一小部分情况外都是过度的。
答案 2 :(得分:5)
commit()
可能会返回false。
查看commit()
和apply()
之间的区别,以获得更清晰的想法(取自this site)
应用()
这会立即将数据保存到内存中并保存数据 磁盘在一个单独的线程上。所以没有机会阻挡主力 线程(你的应用程序不会挂起)。
这是首选技术,但此后才可用 Gingerbread(API 9,Android 2.3)。
提交()
调用此方法会将数据保存到文件中,但过程是 在调用它的线程中执行,停止其他所有操作 直到保存完成。成功完成后返回true, 失败时假。
如果您需要确认保存成功,请使用commit() 数据或者您是否正在为姜饼设备开发。承诺() 自API 1以来一直可用
答案 3 :(得分:3)
我将从另一个角度完全接近这个问题。
有几种方法可以解决这个问题。
我做的是当我的程序第一次运行时,我 将我的共享首选项值初始化为测试值,以便检查是否存在 已被改变。
例如:
editor.putInt("key", -1);
然后在我正在检索首选项值的活动中:
int mySavedInt = this.pref.getInt("key", howIgetMyInt)
if(mySavedInt==-1){
// I know it's not my saved int :) and hasn't been set.
}
或者实际使用共享首选项本身来确定共享首选项 您正在尝试验证已更新。
例如
String getStatus = pref.getString("checkMySharedPreferences", "nil");
if (getStatus.equals("true")) {
// DO something.
} else {
Toast.makeText(this, "Set your preferences",
Toast.LENGTH_SHORT).show();
}
然后,当您设置共享偏好设置时,您可以将此值设置为" true":
editor.putString("checkMySharedPreferences", "true");
editor.commit();
另一个建议是确保在更新共享首选项之前验证任何数据。 这样,如果数据无效,则不会设置共享首选项。
if(my data is valid){
my shared preferences
commit
}
最后的建议是进行循环检查(因为您在此过程中不安全)以及获取共享首选项的数据并提交它。检查用户输入是否等于新的共享首选项。虽然我不认为这是必要的。
要记录这些事件,只需在适用的位置添加日志行。
另外,只是旁注,我认为如果没有设置异常,抛出异常一定是好习惯,我相信管理程序流程可以通过条件语句更好地处理显然会出现runtime
错误。保存错误处理以验证用户输入。