博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 面试(六):你已经用 SharedPrefrence 的 apply() 替换 commit() 了吗?
阅读量:6880 次
发布时间:2019-06-26

本文共 4865 字,大约阅读时间需要 16 分钟。

这是 的第六期。本期我们将来探讨一个有趣的东西 —— SharePrefrence 的两种提交方式 apply()commit()

往期内容传递:

开始

其实非常有趣,我们经常在开发中使用 SharePrefrence 保存一些轻量级数据,比如判断是否是首次启动,首次启动进入引导页,否则直接到主页面,或者是其它的一些应用场景。

而我们也耳熟能详这样的写法。

  • 根据 Context 获取 SharedPreferences 对象
  • 利用 edit() 方法获取 Editor 对象。
  • 通过 Editor 对象存储 key-value 键值对数据。
  • 通过 commit() 方法提交数据。
public class SplashActivity extends AppCompatActivity {    public static final String SP_KEY = "com.zxedu.myapplication.SplashActivity_SP_KEY";    public static final String IS_FIRST_IN = "com.zxedu.myapplication.SplashActivity_IS_FIRST_IN";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 一些业务代码        ......              SharedPreferences preferences = getSharedPreferences("name",MODE_PRIVATE);        if (preferences.getBoolean(IS_FIRST_IN,true)){            // 跳转引导页面            startActivity(new Intent(this,GuideActivity.class));            finish();        }else{            // 跳转主页面            startActivity(new Intent(this,MainActivity.class));        }    }}public class GuideActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_splash);        getSharedPreferences(SplashActivity.SP_KEY,MODE_PRIVATE).edit().putBoolean(SplashActivity.IS_FIRST_IN,false).apply();    }}

从代码中可以看到,一阵混乱操作,没啥特别的地方,但早期开发的人员应该知道,之前我们都是比较青睐 commit() 进行提交的。而现在 Android Studio 在我们使用 commit() 直接提交的时候会直接报黄色警告。

nanchen

commit() 和 apply() 到底有什么异同?

先说说相同点:

  • 二者都是提交 Prefrence 修改数据;
  • 二者都是原子过程。

不同点直接上源码吧,先看看 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.         *         * 

Note that when two editors are modifying preferences at the same * time, the last one to call commit wins. * *

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

综合一下 commit() 方法的注释也就是两点:

  • 会返回执行结果。
  • 如果不考虑结果并且是在主线程执行可以考虑 apply()

再看看 apply() 方法的定义:

/**         * 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.         *         * 

Note that when two editors are modifying preferences at the same * time, the last one to call apply wins. * *

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

As {@link SharedPreferences} instances are singletons within * a process, it's safe to replace any instance of {@link #commit} with * {@link #apply} if you were already ignoring the return value. * *

You don't need to worry about Android component * lifecycles and their interaction with apply() * writing to disk. The framework makes sure in-flight disk * writes from apply() complete before switching * states. * *

The SharedPreferences.Editor interface * isn't expected to be implemented directly. However, if you * previously did implement it and are now getting errors * about missing apply(), you can simply call * {@link #commit} from apply(). */ void apply();

略微有点长,大概意思就是 apply()commit() 不一样的地方是,它使用的是异步而不是同步,它会立即将更改提交到内存,然后异步提交到硬盘,并且如果失败将没有任何提示。

总结一下不同点:

  • commit() 是直接同步地提交到硬件磁盘,因此,多个并发的采用 commit() 做提交的时候,它们会等待正在处理的 commit() 保存到磁盘后再进行操作,从而降低了效率。而 apply() 只是原子的提交到内容,后面再调用 apply() 的函数进行异步操作。
  • 翻源码可以发现 apply() 返回值为 void,而 commit() 返回一个 boolean 值代表是否提交成功。
  • apply() 方法不会有任何失败的提示。

那到底使用 commit() 还是 apply()?

大多数情况下,我们都是在同一个进程中,这时候的 SharedPrefrence 都是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,我们非常建议用 apply() ,当然需要确保操作成功且有后续操作的话,还是需要用 commit() 的。

做不完的开源,写不完的矫情。欢迎扫描下方二维码或者公众号搜索「nanchen」关注我的微信公众号,目前多运营 Android ,尽自己所能为你提升。如果你喜欢,为我点赞分享吧~

nanchen

转载地址:http://uxgfl.baihongyu.com/

你可能感兴趣的文章
《精通ArcGIS Server 应用与开发》——2.2 ArcGIS Server架构
查看>>
《UNIX网络编程 卷1:套接字联网API(第3版)》——2.10 TCP端口号与并发服务器...
查看>>
Centrifugo —— 用 Golang 实现的实时消息通信平台
查看>>
《善用佳软:高效能人士的软件应用之道》一2.6 小工具之计算器
查看>>
《Web前端工程师修炼之道(原书第4版)》——关于浏览器
查看>>
关于CKEditor4.5.6的使用,自定义toolbar配置,上传图片案例(SpringMVC+MyBatis案例),自定义行高,去编辑器的中内容,将编辑器中内容设置到指定的位置等...
查看>>
Ejoy2D —— 来自云风的开源游戏图形引擎
查看>>
Linux主机肉鸡木马minerd导致CPU跑满
查看>>
Organelle —— 支持编程的智能音频设备,能玩!
查看>>
phpMyAdmin 4.0.0-rc4 发布
查看>>
《教孩子学编程(Python语言版)》——第2章 海龟作图—用Python 绘图 2.1 第一个海龟程序...
查看>>
AutoreleasePool的那些事
查看>>
vue服务器端渲染(SSR)实战
查看>>
「原码 反码 补码 移码」一探究竟(中)
查看>>
CSS 你到底有多少长度单位?
查看>>
Linux Shell脚本系列之二
查看>>
设计模式--代理模式(Proxy Pattern)
查看>>
稀疏数组
查看>>
HTML5 标签 canvas
查看>>
react-router@4.0 使用方法和源码分析
查看>>