Sharedpreferences是Android平台上一个轻量级的存储类,可以用于保存应用程序的各种配置信息,如应用设置里面的各种开关、是否打开音效、是否使用震动效果、小游戏的玩家积分等,其本质是以“键-值”对的方式保存数据到本地的 xml 文件中,其文件保存在 /data/data//shared_prefs 目录下。
核心原理:以“键-值”对的方式保存数据到本地的 xml 文件中,具体实现是在 SharedPreferencesImpl 里面使用Map来管理,xml 文件的具体保存路径是在 /data/data//shared_prefs 目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。
SharedPreferences本身是一 个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下:
Context.MODE_APPEND: 追加方式存储
Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。
Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。
Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写
Context.MODE_MULTI_PROCESS: 适用于多进程访问(目前已被废弃,google官方推荐使用ContentProvider来实现进程间共享访问)
Editor有如下主要重要方法:
SharedPreferences.Editor clear():清空SharedPreferences里所有数据
SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据
SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项
boolean commit(): 当Editor编辑完成后,使用该方法提交修改
首次创建SharedPreferences对象(即SharedPreferences初始化时),会根据文件名将文件下内容一次性加载到mMap容器中,每当我们edit都会创建一个新的EditorImpl对象,当修改或者添加数据时会将数据添加到mModifiled容器中,然后commit或者apply操作比较mMap与mModifiled数据修正mMap中最后一次提交数据然后写入到文件中。
使用SharedPreferences的 get 方法获取数据时是直接从 mMap 中读取的,直接从 mMap 中读取数据可以提高读取的效率,但也间接表明 SharedPreferences 不适合存放 大的key和value,因为存放大的key和value在SharedPreferences中,数据会一直存储在内存中得不到释放占用较大的内存,容易引发系统 GC,严重时导致界面丢帧甚至ANR。
从 commit()和 apply() 两个方法的区别中可以得出两个方法的使用场景:在一个进程中,由于sharedPreference是单实例的,只要保证内存缓存正确就能保证运行时数据的正确性,一般不会出现并发冲突,所以如果对提交结果不关心的话,建议使用apply(),只有在关心提交结果的情况下使用 commit()。
对于多进程的应用,若在某一个进程获取到的SP值不是最新的,很可能是创建SP的时候指定的模式有问题,应该指定为多进程的模式:Context.MODE_MULTI_PROCESS,设置之后可以实时读取Sharedpreferences中修改后的值。
通过Context.MODE_MULTI_PROCESS属性使用SharedPreferences虽然可以实现多进程访问SharedPreferences数据的问题,但是这种方式的多进程共享数据可能会出现数据不一致的问题。问题原因是因为进程间是不能内存共享的,每个进程操作的SharedPreferences都是一个单独的实例,SharedPreferences数据写入的时机也不确定,而且不能通过加锁解决多进程的数据同步,从而导致了多进程间通过SharedPreferences来共享数据是不安全的。
结论:Context.MODE_MULTI_PROCESS这个属性Google已经废弃,不建议使用了,对于多进程间的数据共享建议使用ContentProvider。若要用Sharedpreferences实现多进程数据共享,只能在确保不会同时操作SharedPreferences数据的前提下使用,但这个条件很难保证,所以建议最好不要使用。
如果要访问其他应用中的Preference,必须满足的条件是,要访问的应用的Preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。
举例,假如有个为com.alexlee1987.demo下面的应用使用了下面语句创建了Preference,getSharedPreferences(“demo”, Context.MODE_WORLD_READABLE),现在要访问该Preferences:
首先,需要创建上面的Context,然后通过Context访问Preferences,访问preference时会在应用所在包下的shared_prefs目录找到preference:
Context context = createPackageContext("com.alexlee1987.demo", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = context.getSharedPreferences("demo", Context.MODE_WORLD_READABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 0);
如果不通过创建Context访问其他应用的preference,可以以读取xml文件方式直接访问其他应用preference对应的xml文件,如:
File xmlFile = new File(“/data/data//shared_prefs/itcast.xml”);//应替换成应用的包名。
Sharedpreferences是Android平台上一个轻量级的存储类,可以方便快捷的在本地保存应用的一些信息,Sharedpreferences好用,但也不能滥用,使用过程中建议遵循以下规则: