美文网首页
SharedPreferences随笔

SharedPreferences随笔

作者: fcott | 来源:发表于2018-05-04 15:13 被阅读0次

    SharedPreferences是一种轻型的Android数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。它的存储位置是在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。比较经典的使用方式例如用户输入框对过往登录账户的存储。实现SharedPreferences存储的步骤如下:

    1、根据Context获取SharedPreferences对象
    2、利用edit()方法获取Editor对象。
    3、通过Editor对象存储key-value键值对数据。
    4、通过commit()或apply()方法提交数据。

    那么问题来了,commit和apply到底有什么区别呢,或者说我们如何选择?
    总结一下:
    commit() 是直接同步地提交到硬件磁盘,因此,多个并发的采用 commit() 做提交的时候,它们会等待正在处理的 commit() 保存到磁盘后再进行操作,从而降低了效率。而 apply() 只是原子的提交到内容,后面再调用 apply() 的函数进行异步操作。
    翻源码可以发现 apply() 返回值为 void,而 commit() 返回一个 boolean 值代表是否提交成功。
    apply() 方法不会有任何失败的提示。

    听上去apply是一个非常不错的选择,而且当我们在用commit()方法直接提交的时候,AS会显示如下警告 commit警告.png

    但使用apply()就真的完美无缺吗。非也
    上面说到,commit是直接同步地提交到硬件磁盘,apply只是原子的提交到内容,后面再调用 apply() 的函数进行异步操作。这里的后面,其实是在Activity的onPause的时候去执行,这个时候会有一个问题。我们知道,Activity跳转的时候,比如ActivityA跳转到ActivityB,那么两个Activity的生命周期是:A(onPause)-B(onCreat)-B(onStart)-B(onResume)-A(onStop)。如果我们在ActivityA的onPause中做了耗时操作,将会导致Activity跳转卡顿严重,甚至ANR。
    也许有童鞋会说,sp的加载不是在子线程么,怎么会卡住主线程?子线程IO就一定不会阻塞主线程吗?
    sp为了避免同时读写,在操作的时候挂了一把锁

    private void awaitLoadedLocked() {
        while (!mLoaded) {
            try {
                wait();
            } catch (InterruptedException unused) {
            }
        }
    }
    

    这意味着,apply虽然开了子线程处理,但是activity退出时会等待写入完成 也可能造成anr。
    所以,我们在使用SP的时候,一定要仔细斟酌。不要滥用sp,非轻量级数据,尽量避免使用sp来存储。
    而且在储存多对数据时,不要多次commit。对实时性要求不高的数据,尽量合并commit。避免如下错误写法:

    SharedPreferences sp = getSharedPreferences("test", MODE_PRIVATE);
    sp.edit().putString("test1", "sss").apply();
    sp.edit().putString("test2", "sss").apply();
    sp.edit().putString("test3", "sss").apply();
    sp.edit().putString("test4", "sss").apply();
    

    相关文章

      网友评论

          本文标题:SharedPreferences随笔

          本文链接:https://www.haomeiwen.com/subject/ekmdrftx.html