我是靠谱客的博主 超帅树叶,最近开发中收集的这篇文章主要介绍SharedPreference原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原理

创建

  1. 创建sp文件的File对象
class ContextImpl {
SharedPreferences getSP(String name, int mode) {
...
synchronzed (ContextImpl.class) {
...
file = mSharedPrefsPaths.get(name);
if (file == null) {
file = getSHaredPreferencesPath(name); //就是计算出默认sp文件的路径,用这个路径创建File
mSharedPrefsPaths.put(name, file);
}
}
// 获取sp
return getSharedPreferences(file, mode);
}
}
  1. 创建sp对象
class ContextImpl {
SP getSP(File file, int mode) {
.
synchronized (ComtextImpl.class) {
..
if (sp == null) {
...
sp = new SPImpl(file, mode); // 创建的地方
cache.put(file, sp); // 有缓存的,上面省略了
return sp;
}
}
}
}
  1. 创建时,如果文件存在,则异步解析到内存里
class SPImpl {
SPImpl(File file, int mode) {
...
startLoadFromDisk(); // 新建线程,执行load操作
}
void loadFromDisk() {
...
try {
if (mFile.canRead()) {
.
try {
str = new BufferedInputStream(
new FileInputStream(mFile),
16*1026
); // SP的文件
map = (Map<String, Object>) XmlUtils.readMapXml(str); // 对 XmlPullParser 的封装,解析sp文件到内存里
}
}
}
synchronized (mLock) {
..
try {
if () {
if (map != null) {
mMap = map; // 保存到成员变量
...
}
}
}
}
}
}

修改

获取EditorImpl 来执行修改操作

获取方法是 SPImpl.edit()

class SPImpl {
Editor edit() {
.
return new EditorImpl();
}
}

保存

1. 先把要保存的数据,保存到mModified 里

class SPImpl {
class EditorImpl {
Editor putString(String key, String value) {
synchronized (mEditorLock) {
mModified.put(key, value);
return this;
}
}
}
}

2. 调用apply() 或者 commit() 方法,把修改写入文件里

apply() 方法
  1. toMemeory:就是把数据同步到内存里。在 commitToMemory() 方法里,已经把修改的数据 EditorImpl.mModified 同步到 SPImpl.mMap 里了
  2. disk: 就是把数据写到文件里。调用 enqueueDiskWrite() 同步到disk 里
写到memory
class SPImpl {
class EditorImpl {
void apply() {
.
// 把要修改的数据,更新到mMap里,并用mMap生成 这个result
MemoryCommitResult mcr = commitToMemory();
Runnable awaitCommit = new Runnable() {
void run() {
mcr.writtenToDiskLatch.await(); // 是一个CountDownLatch,本质就是LockSupport.park()
}
};
.
// 这个Runnable 就是执行 CountDownLatch.await()。让线程park()
Runnable postWriteRunnable = new Runnable() {
void run() {
awaitCommit.run();
.
}
}
// 主要是这个函数
SPImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
. // 分发listener的监听,不管
}
// 要修改的数据保存在mModified 里
// 文件里的数据保存在mMap 里
// 用 mModified 数据去修改 mMap里的数据,这样mMap就是修改后的数据了
MemoryCommitResult commitToMemory() {
...
synchronized (SPImpl.this.class) {
...
mapToWriteToDisk = mMap;
...
synchronized (mEditorLock) {
...
for (Map.Entry<String, Object> e : mModified.entrySet()) {
..
if (v == this || v == null) { // 删除
..
mapToWriteToDisk.remove(k); // mapToWriteToDisk 是从文件读取出来的数据。这里是删除
} else {
... // 如果有相同的数据,则continue
mapToWriteToDisk.put(k, v);
}
}
}
}
return new MemoryCommitResult(..., mapToWriteToDisk);
}
}
}
写到disk
  1. “queued-work-looper” 线程中 把修改写入disk,并且执行countDown()
  2. 写入disk 完成后,执行await(),因为已经执行countDown()了,所以没有park线程
class SPImpl {
void enqueueDiskWrite(MemoryCommitResult mcr, Runnable postWriteRunnable) {
.
Runnable writeToDiskRunnable = new Runnable() {
void run() {
synchronized(mWriteToDiskLock) {
// 写入disk
writeToFile(mcr, isSync);
}
...
if (postWriteRunnable != null) {
postWriteRunnable.run(); // 执行 线程的park()
}
}
}
...
// 放到名叫 "queued-work-looper" 的线程里运行writeToDiskRunnable
QueueWork.queue(writeToDiskRunnable, !isSync);
}
}
commit() 方法
class SPImpl {
class EditorImpl {
boolean commit() {
...
// 把修改同步到SPImpl.mMap 中,SPImpl.mMap 也保存到 mcr里
MemoryCommitResult mcr = commitToMemory();
// 在调用commit的线程里,执行写入disk的操作。
SPImpl.this.enqueueDiskWrite(mcr, null);
// 写入disk结束时,会设置 mcr.writeToDiskResult 是否写入成功
return mcr.writeToDiskResult;
}
}
}

最后

以上就是超帅树叶为你收集整理的SharedPreference原理的全部内容,希望文章能够帮你解决SharedPreference原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部