SharedPreferences 的commit和apply分析

之前在做项目开发的时候曾经遇到过一个坑,我们的业务需求是点击相应的国家图标进行国家切换包含汇率、url等的切换,所以当时我们考虑的是切换的时候用SharedPreferences来对存储当前的国家代码,所以我们有了以下的代码:

SharedPreferences.Editor editor = PreferenceUtil.getDefaultPreference(DgApplication.getInstance()).edit();
//value是切换的国家代码
editor.putInt(PreferenceUtil.STRING_COUNTRY_CODE, value);
editor.apply();

在完成切换国家动作之后,为了清除之前的缓存数据更新服务器url,我们选择了像微信退出登录那样重启应用。那个时候我们只开放了两个国家,这个坑在最开始的时候并没有出现问题,后来我们开放了第三个国家、第四个国家…然后突然有一天这个潜在的隐患爆发了,测试人员跑来说为什么我切换到新加坡但是我的界面显示的是马币(马来西亚的货币)?那时候我们才开始注意到这个问题。后来一路追踪排查,发现是这句 editor.apply(); 出的锅。解决办法就是将apply改为commit,也就是 editor.commit(); 就可以了。那么现在来想想,都是提交,为什么用apply会出问题,而commit就可以成功处理呢?他们俩之间到底有什么区别呢?google一下发现大家的结论都是:

  1. apply没有返回值而commit返回boolean表明修改是否提交成功
  2. apply是将修改数据原子提交到内存,而后异步真正提交到硬件磁盘;而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内存,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
  3. apply方法不会提示任何失败的提示

虽然这些说法都对,但是我们还是追其根源,看看他们各自的源码里都做了什么“手脚”。

apply和commit都是SharedPreferences的内部接口Editor的一个方法,而他们的实现都在SharedPreferencesImpl类里。

首先我们看看在SharedPreferences.Editor接口里commit方法的定义:

 /**
  * Commit your preferences changes back from this Editor to the
  * {@link SharedPreferences} object it is editing.  This atomically
  * performs the requested modifications, replacing whatever is currently
  * in the SharedPreferences.
  *
  * <p>Note that when two editors are modifying preferences at the same
  * time, the last one to call commit wins.
  *
  * <p>If you don't care about the return value and you're
  * using this from your application's main thread, consider
  * using {@link #apply} instead.
  *
  * @return Returns true if the new values were successfully written
  * to persistent storage.
  */
  boolean commit();

这里注释的意思大概是这个提交方法会返回一个修改后的结果,会自动执行修改的请求,替换掉当前Shar

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值