SharedPreference.Editor中commit和apply区别

2015-07-12 Brian Li 更多博文 » 博客 » GitHub »

原文链接 https://bigosg.github.io/android/2015/07/12/whats-the-difference-between-commit-and-apply-in-shared-preference.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


学Android也有段时间了,至今还没写过文章,可能是我懒吧(其实就是懒- -),今天在练习项目的时候,被IDEA一个warning弄懵了,看下图:

commit-warning

首先commit()方法是为SharedPreference保存数据用的,IDEA警告意思是说,建议用apply()方法代替。commit()方法保存数据是马上执行的,而apply()方法会在后台执行。

这是毛意思呢? 反正我先注释了commit()方法,添加了apply()方法,警告信息就没有了,why? why? why?,这是为什么?

然后google大法搜索了下,这两个方法区别是这样的:

  • commit方法有boolean返回值,表示保存是否成功的.
  • apply方法是void的.
  • commit方法是同步执行保存.
  • apply方法是异步执行保存(这就是IDEA的警告意思吧).

应该到底用哪个方法呢? 我的结论是视实际情况而定,如不关心是否保存成功,就可以用异步的apply方法,相反,在乎保存返回值的,则用commit方法.如果出现并发情况,那么肯定是用异步的apply方法,这是如果用了commit方法的话,就有可能会导致阻塞. apply方法是现将数据立马存到内存中,然后会异步的去保存到目录文件去.

抄一段API文档中的说明:

Unlike commit(), which writes its preferences out to persistent storage synchronously, apply() commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won't be notified of any failures. If another editor on this SharedPreferences does a regular commit() while a apply() is still outstanding, the commit() will block until all async commits are completed as well as the commit itself.

As SharedPreferences instances are singletons within a process, it's safe to replace any instance of commit() with apply() if you were already ignoring the return value.

官方API-apply()方法解释(需翻墙){:target="_blank"}

在获取SharedPreferences对象时,大家会用那种方式呢?

  • Activity.getPreferences(int mode)
  • PreferenceManager.getDefaultSharedPreferences(Context context);
  • ContextWrapper.getSharedPreferences(String name, int mode)

然并卵,1和2其实还是调用的第三个方法,如下:

{% highlight java %}

public SharedPreferences getPreferences(int mode) { return getSharedPreferences(getLocalClassName(), mode); }

{% endhighlight %}

Activity的方法,调用的还是父类的getSharedPreferences方法,就是第三个方法,只不过这里保存文件的文件名称,使用默认的类名罢了.

{% highlight java %}

public static SharedPreferences getDefaultSharedPreferences(Context context) { return context.getSharedPreferences(getDefaultSharedPreferencesName(context), getDefaultSharedPreferencesMode()); }

private static String getDefaultSharedPreferencesName(Context context) { return context.getPackageName() + "_preferences"; }

private static int getDefaultSharedPreferencesMode() { return Context.MODE_PRIVATE; } {% endhighlight %}

第二种,在明显不过了,tmd还是调用第三个啊,文件名称和操作模式mode都有默认值。

{% highlight java %} public SharedPreferences getSharedPreferences(String name, int mode) { return mBase.getSharedPreferences(name, mode); } {% endhighlight %}

这是祖宗,自定义文件名称,操作模式可选,完美.