首页 > 代码库 > 【边做项目边学Android】知识点:SharedPreferences

【边做项目边学Android】知识点:SharedPreferences

Ⅰ. 简介

很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的 QQ,用户可以设置是否允许陌生人添加自己为好友。对于软件配置参数的保存,如果是window软件通常我们会采用ini文件进行保存,如果是j2se应用,我们会采用properties属性文件或者xml进行保存。如果是Android应用,我们最适合采用什么方式保存软件配置参数呢?Android 平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。SharedPreferences 类似过去Windows系统上的ini配置文件,但是它分为多种权限,可以全局共享访问,最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比SQLite要好不少,如果真的存储量不大可以考虑自己定义文件格式。xml 处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。

使用 SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs目录下(需要用户的root权限)

SharedPreferences的使用非常简单,能够轻松的存放数据和读取数据。SharedPreferences只能保存简单类型的数据,例如,String、int等。一般会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中,再用SharedPreferences保存。这种方式应该是用起来最简单的Android读写外部数据的方法了。他的用法基本上和 J2SE(java.util.prefs.Preferences)中的用法一样,以一种简单、透明的方式来保存一些用户个性化设置的字体、颜色、位置等参数信息。一般的应用程序都会提供“设置”或者“首选项”的这样的界面,那么这些设置最后就可以 通过Preferences来保存,而程序员不需要知道它到底以什么形式保存的,保存在了什么地方。当然,如果你愿意保存其他的东西,也没有什么限制。只 是在性能上不知道会有什么问题。


Ⅱ. 使用

使用SharedPreferences保存key-value对的步骤如下:

(1)使用Activity类的getSharedPreferences方法获得SharedPreferences对象,其中存储key-value的文件的名称由getSharedPreferences方法的第一个参数指定。

(2)使用SharedPreferences接口的edit获得SharedPreferences.Editor对象。

(3)通过SharedPreferences.Editor接口的putXxx方法保存key-value对。其中Xxx表示不同的数据类型。例如:字符串类型的value需要用putString方法。

(4)通过SharedPreferences.Editor接口的commit方法保存key-value对。commit方法相当于数据库事务中的提交(commit)操作。


具体代码的书写流程为:

A、存放数据信息

//1、打开Preferences,名称为setting,如果存在则打开它,否则创建新的Preferences

SharedPreferences settings = getSharedPreferences(“setting”, 0);

//2、让setting处于编辑状态

SharedPreferences.Editor editor = settings.edit();

//3、存放数据

editor.putString(“name”,”ATAAW”);

editor.putString(“URL”,”ATAAW.COM”);

//4、完成提交

editor.commit();

因为SharedPreferences背后是使用xml文件保存数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Android自动加上。方法的第二个参数指定文件的操作模式,共有四种操作模式。

  • Activity.MODE_PRIVATE,//默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中,可以使用Activity.MODE_APPEND 
  • Activity.MODE_WORLD_READABLE,//表示当前文件可以被其他应用读取, 
  • Activity.MODE_WORLD_WRITEABLE,//表示当前文件可以被其他应用写入; 
                                         //如果希望文件被其他应用读和写,可以传入:Activity.MODE_WORLD_READABLE+Activity.MODE_WORLD_WRITEABLE
  • Activity.MODE_APPEND//该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件 

如果希望SharedPreferences背后使用的xml文件能被其他应用读和写,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。

另外Activity还提供了另一个getPreferences(mode)方法操作SharedPreferences,这个方法默认使用当前类不带包名的类名作为文件的名称。


B、读取数据信息

//1、获取Preferences

SharedPreferences settings = getSharedPreferences(“setting”, 0);

//2、取出数据

String name = settings.getString(“name”,”默认值”);//getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值

String url = setting.getString(“URL”,”default”);

//以上就是Android中SharedPreferences的使用方法,其中创建的Preferences文件存放位置可以在Eclipse中查看:

DDMS->File Explorer /<package name>/shared_prefs/setting.xml


运行机制

Context内部实现

getSharedPreferences()方法本身是Context这个接口中定义的一个抽象方法,由ContextImpl类负责实现。

1 、调用getSharedPreferences()获取对应的的文件,该函数实现功能如下:

//Context类静态数据集合,以键值对保存了所有读取该xml文件后所形成的数据集合
private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
   new HashMap<File, SharedPreferencesImpl>();
 
@Override
public SharedPreferences getSharedPreferences(String name, int mode){
//其所对应的SharedPreferencesImpl对象 ,该对象已一个HashMap集合保存了我们对该文件序列化结果
SharedPreferencesImpl sp; 
     File f = getSharedPrefsFile(name);  //该包下是否存在对应的文件,不存在就新建一个
     synchronized (sSharedPrefs) {       //是否已经读取过该文件,是就直接返回该SharedPreferences对象
         sp = sSharedPrefs.get(f);
         if (sp != null && !sp.hasFileChanged()) {
             //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
             return sp;
         }
     }
     //以下为序列化该xml文件,同时将数据写到map集合中    
     Map map = null;
     if (f.exists() && f.canRead()) {
         try {
             str = new FileInputStream(f);
             map = XmlUtils.readMapXml(str);
             str.close();
         }
         ...
     }
    
     synchronized (sSharedPrefs) {
         if (sp != null) {
             //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
             sp.replace(map);   //更新数据集合
         } else {
             sp = sSharedPrefs.get(f);
             if (sp == null) { 
              //新建一个SharedPreferencesImpl对象,并且设置其相关属性
                 sp = new SharedPreferencesImpl(f, mode, map); 
                 sSharedPrefs.put(f, sp);
             }
         }
         return sp;
     }
}

2、 SharedPreferences 不过是个接口,它定义了一些操作xml文件的方法,其真正实现类为SharedPreferencesImpl ,该类是ContextIml的内部类,该类如下:

//这种形式我们在分析Context ContextIml时接触过
//SharedPreferences只是一种接口,其真正实现类是SharedPreferencesImpl类
private static final class SharedPreferencesImpl implements SharedPreferences{
private Map mMap;  //保存了该文件序列化结果后的操作, 键值对形式
//通过key值获取对应的value值
public String getString(String key, String defValue) {
         synchronized (this) {
             String v = (String)mMap.get(key);
             return v != null ? v : defValue;
         }
     }
...
//获得该SharedPreferencesImpl对象对应的Edito类,对数据进行操作
public final class EditorImpl implements Editor {
private final Map<String, Object> mModified = Maps.newHashMap(); //保存了对键值变化的集合
}
} 


 

参考:

http://blog.csdn.net/wxyyxc1992/article/details/17222841

【边做项目边学Android】知识点:SharedPreferences