1.背景
在用文件存储的时候,我们体验到使用内部存储的方便快捷,即既不用申请权限,也不用指定路径,不过还是有不方便的地方,特别是在存储程序配置信息时,程序的配置信息往往是”键-值“的形式,例如
是否夜间模式-否
语言-中文
全屏浏览-否
对这些信息的存取,我们需要另外写解析类工具,不过,已有现成的轮子可以使用,那就是Android提供的SharedPreferences类。
2.什么是SharedPreferences
SharedPreferences由share和preferences组成,share是共享,preferences意为偏好,可理解成偏好设置,例如Android Studio菜单里有Preference,点进去是各种设置,从SharedPreferencess名称可以看出,这个类和设置有关系,那么又是谁的设置,自然是应用程序的设置,而为什么share?个人认为是因为SharedPreferences是单例对象,可在整个应用内数据共享访问。
Sharepreferences实际上是一个轻量级的存储类,这个类的功能是以“键-值”对的方式保存数据的xml文件,不过只支持一些Java基本数据类型,包括int、boolean、float、long、String、StringSet,支持的数据类型对存储程序配置文件基本够用,如果想保存更复杂的数据类型,还得使用上个博客提到的文件存储。xml文件保存路径在/data/data/shared_prefs目录下,这个存储目录Sharepreferences自动创建,实际在使用的时候,我们根本不需要关心这个目录。
3.SharedPreferences用法
3.1 获取SharedPreferences对象
Android中提供了两种方法用于得到 SharedPreferences对象。
- Context类中的getSharedPreferences(String name,int mode)方法,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,第二个参数用于指定操作模式,主要有以下两种模式可以选择:
-
Context.MODE_PRIVATE
(默认):只有当前的应用程序才能对文件进行读写,该模式下,写入内容覆盖原文件内容; -
Context.MODE_APPEND
:该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件;
其实还有另外两种操作模式,分别是Context.MODE_WORLD_READABLE
和Context.MODE_WORLD_WRITEABLE
,用来控制其他应用是否有权限读写该文件,出于安全上的原因,在Android 4.2以后已经被废弃。
context.getSharedPreferences("Storage",MODE_PRIVATE)
- Activity类中的getPreferences(int mode)方法,这个方法只需设置模式,文件名默认使用类名。我们注意到这个方法名没有
Shared
字眼,因为通过这个方法获得的SharedPreferences对象只能在该Activity中使用,没有共享属性了.
其实还有一个方法获取SharedPreferences,那就是使用PreferenceManager类中的getDefaultSharedPreferences(Context context)方法,该接收一个 Context 参数,该方法自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。但PreferenceManager类在最近的Android 10被废弃,Android 10是去年(2019)公布,这意味着使用Android 10的设备占比不算太大,还有大量的旧版本仍支持PreferenceManager,是否考虑使用由读者自己斟酌,就个人而言,前两个方法已经够用了,考虑到以后的兼容性,建议不使PreferenceManager类来获取SharedPreferences对象。
3.2 使用SharedPreferences存取数据
- 存储数据
获取SharedPreferences只是第一步,还不能直接存取数据,还需要调用SharedPreferences的编辑器Editor,获取方法是调用SharedPreferences对象的edit()方法,代码如下
SharedPreferences.Editor editor = sharedPreferences.edit();
有了Editor之后,便可以调用方法存数据,想要存储什么数据类型,put对应数据类型即可,最后记得使用commit()或者apply()(关于commit()和supply()方法的差异在下文提及)方法提交,示例代码如下
//存String数据类型
editor.putString("name","Li Lei");
//存Int数据类型
editor.putInt("age", 33);
//存Boolean数据类型
editor.putBoolean("rich",false);
//存float数据类型
editor.putFloat("deposit",123.12f);
//最后提交
editor.commit();
提交之后,我们可以在data/data/package/shared_prefs
目录下找到对应的xml文件,xml文件里的内容是刚才提交的数据。
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="name">Li Lei</string>
<boolean name="rich" value="false" />
<float name="deposit" value="123.12" />
<int name="age" value="33" />
</map>
- 读取数据
读取数据不需要使用编辑器Editor,直接使用SharedPreferences对象即可,例如要获取刚刚存的存款deposit,因为是float数据类型,使用getFloat(String key, float defValue)方法,这个方法要传入两个参数,第一个对应的键的名称,第二个是如果没有值,则返回的默认值。其他数据类型类似
sharedPreferences.getFloat("deposit",0.0f);sharedPreferences.getString("deposit","NOBODY");sharedPreferences.getBoolean("rich",false);
- 删除指定数据和清空数据
这又用回编辑器Editor,删除是使用Editor的remove(String key)函数,输入参数是键的名称,清空数据使用clear()函数,最后要使用commit()提交,也就是说,使用Editor做的任何操作,最后都要使用commit()或apply()方法提交才有效果。
editor.remove("name");
editor.commit();
editor.clear();
editor.commit();
- commit()和supply()方法的区别
- commit()是直接同步保存到磁盘,supply()是先保存到内存再开线程保存到磁盘
- commit()有返回值,可知道是否保存成功,supply()无返回值,是否保存成功无法知晓,除非打开xml文件查看;
- 因为commit()是同步提交,提交过程将阻塞,直到所有的数据提交完毕,因此当数据量大时,且不关心保存成功与否,优先使用apply();
4.总结
SharedPreferences是Android针对程序配置文件保存推出的一个轻量存储类,支持java基本数据类型,因为是单例对象,全局可共享访问,大大方便了在程序各个位置获取程序的设置数据,使用简单,创建对象,获取SharedPreferences的编辑器Editor即可存取数据。