android SharedPreferences解析

一,获取SharedPreferences对象

从Activity获取SharedPreferences对象的代码追踪,可以发现其是在ContextWrapper中通过context对象方法获取的。

mBase.getSharedPreferences(name, mode)

那context中是如何创建对象的呢:

1.context对象

Activity中context对象的创建,肯定是要从Activity的创建找起。

ActivityThread中:handleMessage->handleLaunchActivity->performLaunchActivity->createBaseContextForActivity

ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);

在createBaseContextForActivity中可以看到ContextImpl是创建context的主要类。

2.ContextImpl
return new ContextImpl(null, mainThread,
                packageInfo, activityToken, null, false, null, null);

通过createActivityContext方法,可以看到appContext对象时new ContextImpl本身创建的。

由此可以知道,contex是ContextImpl对象实现的。

3.创建SharedPreferences对象

既然知道context对象的实现类,就可以找出SharedPreferences如何创建了。

在getSharedPreferences方法中

File prefsFile = getSharedPrefsFile(name);
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;

这段代码可以知道,先获得存储数据的文件,然后创建SharedPreferencesImpl实例,SharedPreferencesImpl就是实现SharedPreferences的实现类。

3.1 获取存储数据的文件

getSharedPrefsFile中:

return makeFilename(getPreferencesDir(), name + ".xml");

getPreferencesDir中:

mPreferencesDir = new File(getDataDirFile(), "shared_prefs");

getDataDirFile中

return mPackageInfo.getDataDirFile();

可以看出,存储数据的文件是在app所在数据目录中创建的一个shared_prefs目录下的文件。简单来说如下:

new File("/data/data/"+context.getPackageName()+"/shared_prefs/"+shareName+".xml")
3.2 获取SharedPreferencesImpl对象
SharedPreferencesImpl(File file, int mode) {
        mFile = file;
        mBackupFile = makeBackupFile(file);
        mMode = mode;
        mLoaded = false;
        mMap = null;
        startLoadFromDisk();
    }

makeBackupFile创建了一个备份文件,在startLoadFromDisk则使用线程获取存储文件中的值存储在mMap中,利用备份文件和mLoaded配合使用在多线程下使用SharedPreferences获取存储数据更加安全。

4.获取对象中的参数mode
  • Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
  • Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件.
  • Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件.
  • MODE_WORLD_READABLE:表示当前文件可以被其他应用读取.
  • MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入.

mode主要在writeToFile中存储数据后使用,而writeToFile在enqueueDiskWrite中使用,enqueueDiskWrite主要在apply方法中和commit方法中起作用,而这两个方法是修改数据后提交的方法。所以mode的功能是在写入数据后,更改存储文件的权限作用

二,使用

1 写入

以下是简单写入操作。

Editor editor = sharedPreferences.edit();
editor.putString(key, value);
editor.commit();
editor.clear();

其中Editor是操作数据写入的主要对象,EditorImpl是其实现类。

put操作是将键值对存入Editor的mModified对象中,mModified是个map对象。

commit(apply)操作是将mModified对象内存中的数据,写入磁盘文件中。

先使用MemoryCommitResult对象存储mModified中的数据,MemoryCommitResult对象主要是方便对数据写入磁盘操作,里面含有操作状态。

下面这个方法是实现数据写入磁盘的方法

SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);

而这个方法中,writeToFile方法是实现数据的写入。简略为:

......
if (!mBackupFile.exists()) {
    if (!mFile.renameTo(mBackupFile)) {
        Log.e(TAG, "Couldn't rename file " + mFile
              + " to backup file " + mBackupFile);
        mcr.setDiskWriteResult(false);
        return;
    }
} else {
    mFile.delete();
}
//写入数据操作省略
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
......

可以看出,mBackupFile又起到了多线程使用安全的作用,而设置的model,在写入完成后,设置了文件的权限。

2.读取数据

一下是简单的获取数据操作

SharedPreferencessharedPreferences= getSharedPreferences(name,   
model);   
String value =sharedPreferences.getString(key, defValue);   

与写入不同,它不需要Editor,直接获取数据mMap对象中的数据。

3.不同应用间读取数据

我们已经知道mode的作用,也知道存储文件是通过context对象从对应的应用文件中创建的。所以要读取其他应用的文件,需要两个条件:

  • 要读取应用的context对象,从而获取SharedPreferences对象
  • 对应SharedPreferences文件的model要设置为可被其他应用读(写)。
Context otherAppsContext = createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY);  
  
SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences(name, Context.MODE_WORLD_READABLE);  
  
String value = sharedPreferences.getString(key, defvalue);  

总结

SharedPreferences是将数据存储在对应应用目录下shared_prefs文件夹下的xml文件中,通过context获取SharedPreferences对象,通过Editor操作数据的写入,mode设置SharedPreferences的模式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339