美文网首页
2020-01-03 SharePreferences的appl

2020-01-03 SharePreferences的appl

作者: Yangxy_Lazy | 来源:发表于2020-01-03 17:20 被阅读0次

    一、SharePreference的基本使用

    • 获取sp对象
    private var sp = context.getSharedPreferences(user_sp, Context.MODE_PRIVATE)
    
    • 通过editor对数据进行保存操作等
    val edit = sp.edit()
    when (value) {
         is String -> edit.putString(key, value)
         is Int -> edit.putInt(key, value)
         is Long -> edit.putLong(key, value)
         is Float -> edit.putFloat(key, value)
         is Boolean -> edit.putBoolean(key, value)
    }
    //提交事务
    - ①edit.apply() ——>没有返回值
      
    - ②edit.commit() ——> 返回boolean
    
    • 获取数据
    sp.getLong(key, 0L)
    

    二、commit 实现

    image-20200103161950921.png
    • 先同步内存
    • enqueueDiskWrite(),写入磁盘。postWriteRunnable 传的null.通常情况下在mDiskWritesInFlight(正在执行的写入磁盘操作的数量)为1的时候,直接在当前所在线程执行写入磁盘操作。否则还是异步到QueuedWork中去执行。commit()时,写入磁盘操作会发生在当前线程的说法是不准确的。
    • 执行mcr.writtenToDiskLatch.await(); MemoryCommitResult 中有个一个CountDownLatch 成员变量,他的具体作用可以查阅其他资料。当前线程执行会堵塞在这,直到mcr.writtenToDiskLatch满足了条件。也就是当写入磁盘成功之后,会继续执行下面的操作
    • commit提交之后会有返回结果,同步堵塞直到有返回结果(一般不需要返回结果,所以用apply)

    三、apply实现

    • 加入到QueuedWork中,是一个单线程的操作。

    • 没有返回结果。

    • 默认会有100ms的延迟,延迟写入磁盘。

    四、commit 与apply的区别

    • commit()方法是同步的有返回结果,同步保证使用Countdownlatch,即使同步但不保证往磁盘的写入是发生在当前线程的。

    • apply()方法是异步的具体发生在QueuedWork中,里面维护了一个单线程去执行磁盘写入操作。

    • commit()和apply()方法其实都是Block主线程。commit()只要在主线程调用就会堵塞主线程;apply()方法磁盘写入操作虽然是异步的,但是当组件(Activity Service BroadCastReceiver)这些系统组件特定状态转换的时候,会把QueuedWork中未完成的那些磁盘写入操作放在主线程执行,且如果比较耗时会产生ANR。

    五、总结

    • 有问题,主线程堵塞。

    • 效率低。

    • 1、优化方案

       *   低频 尽量保证多次edit一个apply,原因上文讲过,尽量维持低频的写入。
      
       *   异步 能用apply()方法提交的就用apply()方法提交,原因这个方法是异步的,有延迟的(100s)
      
       *   小量 尽量维持Sharepreferences的体量小些,方便磁盘快速写入。
      
       *   合规 如果存JSON数据,就不要使用Sharepreferences了,因为SharedPerences本质是xml文件格式存储的,要存储JSON文件需要转义效率很低。不如直接自己编写代码文件读写在App私有目录中存储。
      
    • 2、替代方案

        *   腾讯微信团队的MMKV采用内存映射的方式,解决SharedPreferences的各种问题。
      
        *   原理基于内存映射mmap
      
        *   跨进程操作,需要借助Android平台常规的IPC手段(如,AIDL ContentProvider等)来完成。
      

    相关文章

      网友评论

          本文标题:2020-01-03 SharePreferences的appl

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