android SharedPreference的实现(2)
从sharedpreference中获取值以及从editor中设置值已经在sharedpreferences的具体实现(1)中具体说明,这节的主要目的就是理解sharedpreference的commit过程。
代码1: public boolean commit() { memorycommitresult mcr = committomemory(); sharedpreferencesimpl.this.enqueuediskwrite( mcr, null /* sync write on this thread okay */); try { mcr.writtentodisklatch.await(); } catch (interruptedexception e) { return false; } notifylisteners(mcr); return mcr.writetodiskresult; }
以上就是commit的代码,最终返回执行成功或者失败,具体细节我们先分析下一个对象–memorycommitresult
代码2: private static class memorycommitresult { public long memorystategeneration; public list keysmodified; // may be null public set listeners; // may be null public map maptowritetodisk; public final countdownlatch writtentodisklatch = new countdownlatch(1); public volatile boolean writetodiskresult = false; public void setdiskwriteresult(boolean result) { writetodiskresult = result; writtentodisklatch.countdown(); } }
解释下这个类的具体作用,这个类记录着内存中key-value的变化并将这种变化告诉listener。
memorystategeneration实际上是一种xml配置版本记录,中存在着
mcurrentmemorystategeneration和
mdiskstategeneration,他们的类型均为long,分别记录了一个数值,这个数值表示key-value是否已经发生变化,在commit的时候是否需要写入xml文件。
mdiskstategeneration表示上一次执行commit后xml配置文件版本,
mcurrentmemorystategeneration和
memorystategeneration表示当前xml配置文件的版本,在将key-value写入xml配置文件时,只有
memorystategeneration大于
mdiskstategeneration时,系统才会将key-value写入xml配置文件;
keysmodified表示发生变化的key,发生变化可能是新添加也可能是修改了key对应的value。
listeners表示监听sharedpreference上key变化的监听器;
maptowritetodisk是需要写入xml配置文件的key-value集合;
writetodiskresult表示写入xml配置文件的结果;
writtentodisklatch,在commit将key-value写入xml配置文件时,系统使用
writtentodisklatch让程序阻塞,直到commit写入完成。
介绍完
memorycommitresult,
committomemory()方法,
committomemory()方法代码其实很好分析,主要功能就是记录当前需要写入配置文件的key-value,并将需要写入xml配置文件的key-value全部存储在
maptowritetodisk,同时收集value发生变化的key。
maptowritetodisk初始值为
mmap(
mmap可见sharedpreferences的具体实现1中的介绍)。系统会遍历
mmodified(
mmodified可见sharedpreferences的具体实现1中的介绍),并通过一定的机制将需要写入xml配置文件的key-value值添加到
maptowritetodisk中,同时添加到
keysmodified中;同时修改memorystategeneration。
enqueuediskwrite中执行的核心代码是
writetofile(mcr, isfromsynccommit)方法,接下来我们主要分析下这部分的代码。
在分析这段代码之前,我们需要了解系统在写入配置文件时,有一个保护机制,为原来的配置文件生成一份备份文件,写入成功后删除备份文件,写入失败后从备份文件中恢复。看下写入文件的代码:
try { fileoutputstream str = createfileoutputstream(mfile); .... xmlutils.writemapxml(mcr.maptowritetodisk, str); .... }
我注释了其他代码,只保留了最核心的代码,可以发现最核心的部分就是将需要写入配置文件的xml写入对应的文件输出流。