Android 的 SharedPreferences commit() return 何时为假?
When does Android's SharedPreferences commit() return false?
在我的应用程序中,我将一些数据存储在 SharedPreferences
中 - 它会根据需要工作。
现在我想为一些不正确的情况创建日志消息。
我成功处理了首选项为空或加载时抛出异常的情况。
保存值时唯一可能出现的错误是 commit()
returning false
- 我不知道为什么会发生这种情况以及在这种情况下我应该做什么。
所以我的问题是:
commit()
方法什么时候returnfalse
?
在那种情况下我该怎么办?
可能的解决方案是一次又一次地调用 commit()
(类似于 while (!editor.commit()) {}
)吗?
如果在保存数据时出现问题,commit()
可以 return false。
查看 commit()
和 apply()
之间的区别以获得更清晰的想法(摘自 this site)
apply()
This saves your data into memory immediately and saves the data to
disk on a separate thread. So there is no chance of blocking the main
thread (your app won’t hang).
It is the preferred technique but has only been available since
Gingerbread (API 9, Android 2.3).
commit()
Calling this will save the data to the file however, the process is
carried out in the thread that called it, stopping everything else
until the save is complete. It returns true on successful completion,
false on failure.
Use commit() if you need confirmation of the success of saving your
data or if you are developing for pre-Gingerbread devices. commit()
has been available since API 1
And can while(!editor.commit()) {;} be solution for success anyway?
'commit' 操作是同步的并在 UI 线程上执行,因此,如果每次尝试执行 commit
时都会发生一些不可恢复的错误,您将阻塞您使用此代码的整个 UI 线程和用户将看到 ANR。不好。
另一方面,'apply' 是异步的,因此它不能阻塞 UI 线程,即使您将无限期地执行它。
文档很少提及 'commit' 操作可能会失败(请查看此处 here, here and there). The preferences are stored inside the xml file stored on your internal storage, so one possible failure can be the corrupted xml file. The second one can be found in documentation:
Note that when two editors are modifying preferences at the same
time, the last one to call commit wins.
您对损坏的文件无能为力,而且,不要尝试同时从不同位置修改首选项。 :)
我会完全从另一个角度来解决这个问题。
有几种替代方法可以解决这个问题。
我所做的是当我的程序第一次运行时,我
将我的共享偏好值初始化为测试值,以便我检查它是否
已更改。
例如:
editor.putInt("key", -1);
然后在 activity 中检索偏好值:
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
错误。保存验证用户输入时的错误处理。
首先,你永远不会想做:
while(!editor.commit()) {;}
。如果你想重试一次提交,你会这样做几次而不是永远循环。
关于 commit() returns -1:
commit() 和 apply() 都会对内存进行更改,然后进行调用以将更改写入磁盘 (per source). commit() waits for the disk write to return to return the results. So the answer to your question is: "When saving the preference state to disk fails for your particular commit() call." Since changes were reflected in memory they may or may not be written to disk by another commit() or apply() call before or after your attempted disk write (think racing threads). Since there isn't code to rollback the memory update and SharedPreferences are singletons (per source) 您应用中的其他组件将看到您的更改,即使它们没有保存到磁盘也是如此。
总而言之,循环几次(不是永远)以确保 commit() 写入磁盘似乎可以让您解决间歇性的 I/O 问题,但这种情况很少见 I/O 基于它失败的情况。如果您需要完美的提交范围,您可能希望重新读取磁盘以验证每个 commit() 调用,这对性能有影响,并且对于除了一小部分情况之外的所有情况都是过大的。
在我的应用程序中,我将一些数据存储在 SharedPreferences
中 - 它会根据需要工作。
现在我想为一些不正确的情况创建日志消息。
我成功处理了首选项为空或加载时抛出异常的情况。
保存值时唯一可能出现的错误是 commit()
returning false
- 我不知道为什么会发生这种情况以及在这种情况下我应该做什么。
所以我的问题是:
commit()
方法什么时候returnfalse
?
在那种情况下我该怎么办?
可能的解决方案是一次又一次地调用 commit()
(类似于 while (!editor.commit()) {}
)吗?
commit()
可以 return false。
查看 commit()
和 apply()
之间的区别以获得更清晰的想法(摘自 this site)
apply()
This saves your data into memory immediately and saves the data to disk on a separate thread. So there is no chance of blocking the main thread (your app won’t hang).
It is the preferred technique but has only been available since Gingerbread (API 9, Android 2.3).
commit()
Calling this will save the data to the file however, the process is carried out in the thread that called it, stopping everything else until the save is complete. It returns true on successful completion, false on failure.
Use commit() if you need confirmation of the success of saving your data or if you are developing for pre-Gingerbread devices. commit() has been available since API 1
And can while(!editor.commit()) {;} be solution for success anyway?
'commit' 操作是同步的并在 UI 线程上执行,因此,如果每次尝试执行 commit
时都会发生一些不可恢复的错误,您将阻塞您使用此代码的整个 UI 线程和用户将看到 ANR。不好。
另一方面,'apply' 是异步的,因此它不能阻塞 UI 线程,即使您将无限期地执行它。
文档很少提及 'commit' 操作可能会失败(请查看此处 here, here and there). The preferences are stored inside the xml file stored on your internal storage, so one possible failure can be the corrupted xml file. The second one can be found in documentation:
Note that when two editors are modifying preferences at the same time, the last one to call commit wins.
您对损坏的文件无能为力,而且,不要尝试同时从不同位置修改首选项。 :)
我会完全从另一个角度来解决这个问题。
有几种替代方法可以解决这个问题。
我所做的是当我的程序第一次运行时,我 将我的共享偏好值初始化为测试值,以便我检查它是否 已更改。
例如:
editor.putInt("key", -1);
然后在 activity 中检索偏好值:
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
错误。保存验证用户输入时的错误处理。
首先,你永远不会想做:
while(!editor.commit()) {;}
。如果你想重试一次提交,你会这样做几次而不是永远循环。
关于 commit() returns -1: commit() 和 apply() 都会对内存进行更改,然后进行调用以将更改写入磁盘 (per source). commit() waits for the disk write to return to return the results. So the answer to your question is: "When saving the preference state to disk fails for your particular commit() call." Since changes were reflected in memory they may or may not be written to disk by another commit() or apply() call before or after your attempted disk write (think racing threads). Since there isn't code to rollback the memory update and SharedPreferences are singletons (per source) 您应用中的其他组件将看到您的更改,即使它们没有保存到磁盘也是如此。
总而言之,循环几次(不是永远)以确保 commit() 写入磁盘似乎可以让您解决间歇性的 I/O 问题,但这种情况很少见 I/O 基于它失败的情况。如果您需要完美的提交范围,您可能希望重新读取磁盘以验证每个 commit() 调用,这对性能有影响,并且对于除了一小部分情况之外的所有情况都是过大的。