当前位置: 首页 > 科技观察

明白AndroidAPI中的SharedPreferences

时间:2023-03-16 22:02:08 科技观察

Preference翻译过来就是偏好设置,其实可以看成是Setting的别名。两者名称的区别在于针对的对象不同:设置更倾向于设备的属性,修改设置是改变设备的功能;偏好往往是用户的个性,用户根据个人偏好形成设备。差异化。但总的来说,它们是一致的,都是通过用户的需求来改变设备的体验。在Android开发过程中,你会看到很多在使用的API名称中带有Preference的类和接口。本文将介绍这些“*Prefere*”的功能和用途。在Android提供的API中,有Preference的主要分为两类:一类是android.content包下的SharedPreferences,一类是android.preference包下的Preference。它们分别实现不同的功能,但又相互联系,相互配合,共同控制Android程序。SharedPreferences介绍SharedPreferences以复数形式存在,因为在Android中它用于存储键值对(Key-ValuePair)数据的集合。API包含多种读取对应类型数据的方法:StringgetString(Stringkey,StringdefValue);SetgetStringSet(Stringkey,SetdefValues);intgetInt(Stringkey,intdefValue);longgetLong(Stringkey,longdefValue);floatgetFloat(Stringkey,floatdefValue);booleangetBoolean(Stringkey,booleandefValue);这也说明SharedPreferences能存储的类型仅限于String、int、long、float、boolean这些基本数据类,唯一的集合类型只有Set,它看起来更像是一个不能有重复数据的数组。也可以简单的检查指定的主键是否被替换,或者简单的获取所有键值对的Map:booleancontains(Stringkey);MapgetAll();Android系统工程师在设计SharedPreferences时,把读取的功能放在了SharedPreferences上,而回写的功能则在其内嵌的Editor类上实现,通过调用edit()方法获得一个writer。这使得只读对象的实现变得容易,只要它返回空指针或不可用的Editor对象即可。EditorputString(Stringkey,Stringvalue);EditorputStringSet(Stringkey,Setvalues);EditorputInt(Stringkey,intvalue);EditorputLong(Stringkey,longvalue);EditorputFloat(Stringkey,floatvalue);EditorputBoolean(Stringkey,booleanvalue);Editorremove(Stringkey);SharedPreferences还有一个内嵌接口OnSharedPreferenceChangeListener,实现它唯一的方法onSharedPreferenceChanged(SharedPreferencessharedPreferences,Stringkey),通过下面的方法添加到SharedPreferences对象中,监听其上键值对的增删改查:voidregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListenerlistener);voidunregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListenerlistener);SharedPreferences在Android系统中的实现SharedPreferences和内嵌的Editor其实只是接口定义,并没有实现任何方法。它只是用来制定一个存储键值对的协议,具体的实现方式和存储形式可以是任意的。在Android系统中,默认将这些数据存储在XML格式的文件中,实现类为SharedPreferencesImpl。下面是保存的XML文件的基本格式,它使用数据类型作为XML元素的标签,主键(key)是标签名称属性的值,使用主键对应的值作为value属性的值。但是如果是String类型的话,会作为tag下面的内容,这样可以更好的处理换行,不用转义引号。另外,存储空值的结构也比较特殊。它以null为标签,只有一个name属性,没有其他内容。Idercode.iderzheng.comblog.iderzheng.comma??nual.iderzheng.comAndroid系统将XML文件存放在/data/data/(packagename)/shared_prefs/下,每个XML文件对应一个SharedPreferences对象(实际上是一个SharedPreferencesImpl对象)。但是SharedPreferences是一个接口,不能用来实例化对象,而SharedPreferencesImpl是一个系统隐藏类,不能直接访问和使用,它的构造函数只对包可见。所以不能通过new建立一个SharedPreferences,必须通过Context提供的getSharedPreferences(String,int)获取一个实例。该方法的第一个参数是一个字符串,指定XML文件的名称(不包括“.xml”后缀),该方法将读取相应的文件并创建一个SharedPreferences对象。第二个参数指定文件的访问权限。有4种可选模式。从API17开始,出于安全考虑,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE已被弃用。只能使用MODE_PRIVATE和MODE_MULTI_PROCESS。通常,您可以指定MODE_PRIVATE。从SharedPreferences中读取指定主键的值是非常快的,因为XML中所有的键值对信息都被读取存储在SharedPreferences对象中的Map成员变量中,所以读取是基于内存访问的。使用Editor回写文件无法避免IO操作,所以使用commit()提交修改还是会耗费一些时间。考虑到这一点,Android在API9中引入了apply()方法,将修改后的内容异步写回文件。当然,内存中的键值对信息在写回之前会进行更新,以保证读到的是最新的内容。由于writeback可以是异步的,所以多次调用getSharedPreferences(String,int)可以得到多个SharedPreferences并赋值给不同的变量。如果一个变量被修改,其他对象不会有内容不一致。其实不会出现这种情况,因为所有创建的SharedPreferences都保存在ContextImp的一个静态成员变量中:/***Mapfrompackagename,topreferencename,tocachedpreferences.*/privatestaticArrayMap>sSharedPrefs;这是从程序的包名到XML文件名再到SharedPreferences对象的辅助映射。所以,每次调用getSharedPreferences(String,int)得到的对象其实都是同一个实例,修改操作也应用在同一段内存上,保证了所有访问的一致性。apply()方法也会自动将所有的修改放入队列,并一一写回文件,这样就不会因为顺序错误而覆盖意外错误。所以因为这个缓存机制的存在,多次调用getSharedPreferences(String,int)是非常高效的。回写时,建议使用apply()实现异步操作,而不是使用commit()阻塞主线程。SharedPreferences的使用和例子一般来说,SharedPreferences的名字和主键名是固定的,所以可以定义一些final字符串变量来保存这些名字,在读写的时候使用这些常量变量。对于之前展示的XML对应的代码就如下边所示:privatestaticfinalStringIDER_PREFERENCE="ider-preference";privatestaticfinalStringIDER_PREFERENCE_KEY_NAME="Name";privatestaticfinalStringIDER_PREFERENCE_KEY_SUBSITES="Subsites";privatestaticfinalStringIDER_PREFERENCE_KEY_IS_ANDROID="Android";privatestaticfinalStringIDER_PREFERENCE_KEY_VERSION="Version";privatestaticfinalStringIDER_PREFERENCE_KEY_VERSION_CODE="VersionCode";privatestaticfinalStringIDER_PREFERENCE_KEY_VERSION_NUMBER="VersionNumber";privatestaticfinalStringIDER_PREFERENCE_KEY_NULL="Null";publicvoidwrite(Contextcontext){finalSharedPreferencesspref=context.getSharedPreferences(IDER_PREFERENCE,MODE_PRIVATE);HashSetstrs=newHashSet.add(()";blogs()iderzheng.com");strs.add("code.iderzheng.com");strs.add("manual.iderzheng.com");SharedPreferences.Editoreditor=spref.edit();editor.put字符串(IDER_PREFERENCE_KEY_NAME,“Ider”);editor.putStringSet(IDER_PREFERENCE_KEY_SUBSITES,strs);editor.putBoolean(IDER_PREFERENCE_KEY_IS_ANDROID,true);editor.putFloat(IDER_PREFERENCE_KEY_VERSION,5.0f);editor.putInt(IDER_PREFERENCE_KEY_VERSION_CODE.putLongitor,21);编辑IDER_PREFERENCE_KEY_VERSION_NUMBER,1355);editor.putString(IDER_PREFERENCE_KEY_NULL,null);editor.apply();}publicvoidread(Contextcontext){finalSharedPreferencesspref=context.getSharedPreferences(IDER_PREFERENCE,MODE_PRIVATE);Stringname=spref.getString(IDER_PREFERENCE_KEY_NAME,"");设置strs=spref.getStringSet(IDER_PREFERENCE_KEY_SUBSITES,null);booleanisAndroid=spref.getBoolean(IDER_PREFERENCE_KEY_IS_ANDROID,false);floatversion=spref.getFloat(IDER_PREFERENCE_KEY_VERSION,0);intversionCode=spref.getInt(IDER_PREFERENCE_KEY_VERSION_versionNUMBER,0);.getLong(IDER_PREFERENCE_KEY_VERSION_NUMBER,0);booleanhasKey=spref.contains(IDER_PREFERENCE_KEY_NULL);}由于SharedPreferences的名字可以任意给定,因此使用SharedPreferences可以非常有针对性的创建不同的文件来存放不同的内容。例如,您可以将他们的偏好信息存储在不同用户的名称下。该界面保存布局信息和访问页码。Activity额外实现getPreferences(int)方法获取SharedPreferences,只需要开发者提供文件的打开方式,自动使用Activity的类名作为文件名。SharedPreferences取值时,直接将Map中给定主键的值转换成需要的值,所以如果用putInt存整数,用getBoolean()取,不会自动转换成一个整数Boolean类型,但是会直接抛出异常,所以使用的时候要注意保持类型一致。另外,如果没有存储主键,SharedPreferences会返回null值,而对于String、Set等类型,也可以存储null值,这样就无法判断是否真的是null存储的数据。因此SharedPreferences也提供了contains(Stringkey)方法来检查给定的主键是否真的为null,或者因为没有这样的键值对而返回。前面已经提到了SharedPreferences的优缺点,所以SharedPreferences读取过的文件会缓存在Map中,放在内存中,方便下次直接快速访问,因为这是SharedPreferences的一大优势。但也因为它们都背缓存,存储格式是XML,所以SharedPreferences不应该存储过多的键值对,值的内容也不宜过大。此外,SharedPreferences只支持最基本的类型,存储一些基本的用户信息就足够了。如果你在设备上有root权限,你可以直接访问/data/data/(packagename)/shared_prefs/目录来传输XML文件进行查看。或者直接在adbshell下使用cat命令观察数据变化,非常方便。总的来说,SharedPreferences绝对是存储一些内容少、类型简单的数据的最佳对象。

最新推荐
猜你喜欢