美文网首页
SharedPreferencesImpl源码浅析

SharedPreferencesImpl源码浅析

作者: hubert1002 | 来源:发表于2018-03-30 16:23 被阅读0次

    SharedPreferencesImpl源码浅析

    最近拉取应用ANR日志时发现,大量卡顿发生在SharedPreferences的commit上,查看源码发现底层实现基于锁的实现甚为高明,在此叨一叨其主要实现。

    基本方法分析

    初始化流程为:在contextImp中的 public SharedPreferences getSharedPreferences(String name, int mode) 方法中会返回相应name的sp,里面具体实现为一个缓存hashmap,key为name,value为sp,缓存获取失败时会初始化spImp类,从文件中加载数据。

    基本的get方法:初始化完成后会在内存中创建keyvalue缓存,所以各个activity中获取的sp,调用getValue方法时是很高效的。

    Editor中的commit和apply

    变更sp时,会通过Editor的commit或apply来处理,commit为阻塞式修改,不仅会刷新内存缓存,而且会在当前线程去写文件,可能硬气卡顿,apply为异步修改,刷新内存缓存后,启动异步执行器去写文件,不会引起卡顿。

    commit()
    
    () {
        MemoryCommitResult mcr = commitToMemory()SharedPreferencesImpl..enqueueDiskWrite(
            mcr){
            mcr..await()} (InterruptedException e) {
            }
        notifyListeners(mcr)mcr.}
    
    

    处理逻辑为,先修改内存缓存,再在当前线程写入文件,通过countdownlatch来实现同步等待。

    apply()
    
    () {
        MemoryCommitResult mcr = commitToMemory()Runnable awaitCommit = Runnable() {
                () {
                    {
                        ..await()} (InterruptedException ignored) {
                    }
                }
            }QueuedWork.(awaitCommit)Runnable postWriteRunnable = Runnable() {
                () {
                    .run()QueuedWork.()}
            }SharedPreferencesImpl..enqueueDiskWrite(mcrpostWriteRunnable)notifyListeners(mcr)}
    

    修改内存后,启动异步queuework处理写文件,通过对象锁写完文件后,这里通过postRunable完成,感觉有点绕。

    总结

    从源码来分析其实很简单,两者主要区别有两点:
    1、commit()有返回值,apply()没有返回值。apply()失败了是不会报错的。
    2、apply()写入文件的操作是异步的,会把Runnable放到线程池中执行,而commit()的写入文件的操作是在当前线程同步执行的。
    因此当两者都可以使用的时候还是推荐使用apply(),因为apply()写入文件操作是异步执行的,不会占用主线程资源。

    相关文章

      网友评论

          本文标题:SharedPreferencesImpl源码浅析

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