当Android SharedPreferences提交()返回false?

在我的应用程序中,我在SharedPreferences存储了一些重要的数据 – 它按照我的需要工作。 现在我想为一些不正确的情况创build日志消息。

我有消息的情况下,当首选项是空的或只是在加载时抛出一些exception。 只有commit()方法返回false时,才会出现保存错误的情况 – 我不知道为什么会发生这种情况,我应该怎么做。

所以问题是 – 当commit()方法返回false? 而且可以while(!editor.commit()) {;}成功的解决scheme?

Solutions Collecting From Web of "当Android SharedPreferences提交()返回false?"

首先,你永远不想做: while(!editor.commit()) {;} 。 如果你想重试一次提交,你会这么做几次,而不是永远循环。

关于何时commit()返回-1:commit()和apply()对内存进行更改,然后调用将更改写入磁盘( 每个源 )。 commit()等待磁盘写入返回以返回结果。 所以你的问题的答案是:“保存首选状态到磁盘失败,为您的特定commit()调用”。 由于更改反映在内存中,它们可能会或可能不会在尝试写入磁盘之前或之后通过另一个commit()或apply()调用写入磁盘(请参阅赛跑线程)。 由于没有代码回滚内存更新和SharedPreferences是单身( 每个来源 ),您的应用程序中的其他组件将看到您的更改,即使他们没有保存到磁盘。

总之,循环几次(不是永远)以确保commit()写入磁盘似乎很好,让你经历一个间歇性的I / O问题,但这将是一个罕见的基于I / O的情况下,它会失败。 如果您需要完善的提交范围,您可能需要重新读取磁盘以validation每个提交()调用,这会影响性能,并且对于所有情况都是过度的。

而且可以(!editor.commit()){;}成功的解决scheme?

“提交”操作是同步的,并在UI线程上执行,因此,如果每次尝试执行commit时都会发生一些不可恢复的错误,那么将使用此代码阻止整个UI线程,用户将看到ANR。 不好。
另一方面,'apply'是asynchronous的,所以即使你无限期的执行它也不能阻塞UI线程。
文档中对于“提交”操作可能出现的失败提供了很less的信息(请看这里 , 这里和那里 )。 首选项存储在存储在内部存储的xml文件中,因此一个可能的失败可能是损坏的xml文件。 第二个可以在文档中find:

请注意,当两个编辑器同时修改首选项时,最后一个调用commit的成功。

对损坏的文件几乎没有办法,而且,也不要试图同时修改来自不同地方的偏好。 🙂

如果保存数据有问题, commit()可以返回false。

看看commit()apply()之间的区别来获得一个更清晰的想法(从本网站获取 )

应用()

这将立即将数据保存到内存中,并将数据保存到单独的线程中的磁盘上。 所以没有机会阻止主线程(你的应用程序不会挂起)。

这是首选的技术,但只有自姜饼(API 9,Android 2.3)以来才可用。

承诺()

调用这个会将数据保存到文件中,但是这个过程是在调用它的线程中执行的,在保存完成之前停止其他的一切。 成功完成后返回true,失败则返回false。

如果您需要确认保存数据是否成功,或者您正在开发预姜饼设备,请使用commit()。 提交()已经可用,因为API 1

我会从另一个angular度来解决这个问题。

有几个替代方法来处理这个问题。

我所做的是当我的程序第一次运行时,我将我的共享首选项值初始化为一个testing值,以检查它是否已被更改。

例如:

 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. } 

或者实际使用共享首选项来确定您正在尝试validation的共享首选项是否已更新。

例如。

 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(); 

另一个build议是确保在更新共享首选项之前validation任何数据。 这样,如果数据无效,共享首选项将不会被设置。

 if(my data is valid){ my shared preferences commit } 

最后的build议是做一个循环检查(因为你在这个过程中是不安全的),当你得到共享偏好的数据并提交。 检查用户input是否等于新的共享首选项。 虽然我不认为这是必要的。

logging这些事件,只要在适当的地方添加日志行即可。

此外,只是一个侧面说明,我不认为这是一个很好的做法抛出一个exception,如果他们没有设置,我相信pipe理程序stream可以更好地处理与条件语句显然会有一个runtime错误。 保存error handlingvalidation用户input。