本文主要介绍SharedPreferences和PreferenceActivity的基础知识和用法。

主要资料来源于网络,包括但不限于:

《Android之PreferenceActivity》

《在Android中Preferences数据存储的使用》

《Android的设置界面及Preference使用》

《OnPreferenceChangeListener分析,以及与OnPreferenceClickListener的区别》

《使用PreferenceActivity时,如何获取ListPreference中选中的值》。

1、android文件存储

对Android系统了解的都知道,Android系统有四种基本的数据保存方法,一是SharedPreference,二是文件,三是SQLite,四是ContentProvider。看出来了吧,Preference,对就是使用SharedPreferneces以键值对的形式进行保存的。

2、SharedPreferneces

做软件开发应该都知道,很多软件会有配置文件,里面存放这程序运行当中的各个属性值,由于其配置信息并不多,如果采用数据库来存放并不划算,因为数据库连接跟操作等耗时大大影响了程序的效率,因此我们使用键值这种一一对应的关系来存放这些配置信息。SharedPreferences正是Android中用于实现这中存储方式的技术。
SharedPreferences是以键值对的形式存储数据的,其使用非常简单,能够轻松的存放数据和读取数据。

在具体介绍Android的设置界面的实现之前,我们先来介绍一下预备知识,就是Android数据持久化方法中最简单的一种,即使用Preferences的键值对存储方式。这种方式主要用来存储比较简单的一些数据,而且是标准的Boolean、Int、Float、Long、String等类型。

android.content.SharedPreferences是一个接口,用来获取和修改持久化存储的数据。有三种获取系统中保存的持久化数据的方式:

1). public SharedPreferences getPreferences (int mode)
通过Activity对象获取,获取的是本Activity私有的Preference,保存在系统中的xml形式的文件的名称为这个Activity的名字,因此一个Activity只能有一个,属于这个Activity。
2). public SharedPreferences getSharedPreferences (String name, int mode)
因为Activity继承了ContextWrapper,因此也是通过Activity对象获取,但是属于整个应用程序,可以有多个,以第一参数的name为文件名保存在系统中。
3). public static SharedPreferences getDefaultSharedPreferences (Context context)
PreferenceManager的静态函数,保存PreferenceActivity中的设置,属于整个应用程序,但是只有一个,Android会根据包名和PreferenceActivity的布局文件来起一个名字保存。
通过以上方式取得SharedPreferences后就可以对数据进行读取或者保存了。
保存方式如下:

String STORE_NAME = "Settings"; SharedPreferences settings = getSharedPreferences(STORE_NAME, MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putInt("sourceType", 0); editor.commit(); 获得SharedPreferences,如果需要进行保存等修改操作,首先得通过其edit()方法获得SharedPreferences.Editor,然后就可以通过putInt、putString等方法以键值对(key-value)的方式保存数据,或者remove移除某个键(key),及调用clear方法删除所有内容。最后需要调用commit方法是使修改生效。
读取方式如下:

SharedPreferences settings = getSharedPreferences(STORE_NAME, MODE_PRIVATE); int source = settings.getInt("sorceType", 1); 读取就更加简单了,只要获得SharedPreferences后,就可以通过getInt、getString等方法获取对应键(key)保存着的数据,如果没有找到key,则返回第二个参数作为默认值。

2、PreferencesActivity

在Android开发过程中我们有很大的机会需要用到参数设置功能,那么在Android应用中,我们如何实现参数设置界面及参数存储呢,下面我们来介绍一下Android中的一个特殊Activity–PreferencesActivity。
PreferencesActivity是Android中专门用来实现程序设置界面及参数存储的一个Activity。

2.1 创建PreferencesActivity

如何创建一个PreferenceActivity。 其实Eclipse提供了相应的创建工具,和创建Layout是基本相同的。步骤如下:
创建Android项目,并添加一个Android xml文件。注意,这次选择的不是Layout,而是Preference,而且注意Folder路径是 res/xml.


添加完成之后,在res/xml/下打开添加的preference.xml文件。可以看到Android也为我们提供两种编辑模式,可视化的结构设计及xml源码设计。推荐使用structure进行创建。如图所示:


2.2PrefeneceActivity的基本组成

下面我们看看PrefeneceActivity都提供了哪几种元素可供使用。点击Add按钮,在打开的新窗口中可以看到以下几项:


CheckBoxPreference:CheckBox选择项,对应的值的ture或flase。如图:


EditTextPreference:输入编辑框,值为String类型,会弹出对话框供输入。


ListPreference: 列表选择,弹出对话框供选择。


Preference:只进行文本显示,需要与其他进行组合使用。


PreferenceCategory:用于分组。效果如下:


PreferenceScreen:PreferenceActivity的根元素,必须为它。
RingtonePreference:系统玲声选择。


OK,Preferenc的基本元素介绍完毕,下一节将使用它们创建一个完整的Preference并进行显示。

2.3PreferenceActivity实例

分析MusicPlayer Setting,第一部分为“我的位置”,包括“使用无线网线”和“使用GPS”两个部分,而且都是CheckBox,根据上节学习,应该包括一个PreferenceCategory和两个CheckBoxPreference。
Xml代码

以上代码当然也可以用Android提供的IDE工具直接生成。视频结构如下:

PreferenceCategory属性分析:
title:显示的标题
key:唯一标识(至少在同一程序中是唯一),SharedPreferences也将通过此Key值进行数据保存,也可以通过key值获取保存的信息 (以下相同)。
CheckBoxPreference属性分析:
Key:唯一标识.
title:显示标题(大字体显示)
summary:副标题(小字体显示)
defaultValue:默认值(当然,此处只能是true或false了)
Preference.xml的第二部分为“无线和网络设置”,此部分包括的内容比较多,也稍微复杂,一步一步来分析。
xml代码:

对应的Structure图:

第二部分中前三个都为CheckBoxPreference,不心多说,从开始。
Preference属性分析:
Key:唯一标识.
title:显示标题(大字体显示)
summary:副标题(小字体显示)
dependency:附属(嘛意思),即标识此元素附属于某一个元素(通常为CheckBoxPreference),dependency值为所附属元素的key。上面代码中的Preference元素附属于key等于“apply_bluetooth”的CheckPreference元素,当CheckPreference值为true时,Preference则为可用,否则为不可用。
EditTextPreperence属性分析:
Key:唯一标识.
title:显示标题(大字体显示)
ListPreference属性分析:
Key:唯一标识.
title:显示标题(大字体显示)
dialogTitle:弹出对话框的标题
entries:列表中显示的值。为一个数组,通读通过资源文件进行设置。
entryValues:列表中实际保存的值,也entries对应。为一个数组,通读通过资源文件进行设置。以下代码显示的是arrays.xml文件中内容:

综合部 行政部 外贸部 001 002 003

点击“Add”按钮,就会添加新的标签,我们依次添加一个CheckBoxPreference和ListPreference。属于CheckBoxPreference的特有属性主要为Summary On和Summary Off,比较好理解。下面具体来看下ListPreference属性的填写:


我们可以看到,ListPreference除了继承自Preference的属性外,还有自己ListPreference的属性和继承自DialogPreference的属性。其中属于ListPreference的属性有两个:Entries填的为一个字符串数组,是列表显示出来的值,而Entry Values是长度对应的字符串数组,是和Entries对应的具体的值。DialogPreference只要填一个Dialog title标题和一个取消按钮显示的字即可。在Preference属性的Dependency中我们填写上面一个CheckBoxPreference的Key,这样就会只有在CheckBoxPreference勾选时这个ListPreference才有效。


最后把java文件中的addPreferencesFromResource(R.xml.preferences);改为addPreferencesFromResource(R.xml.preferencesii);
保存运行,看下效果。

RingtonePreference :玲声(暂时没有用到过),暂时略过。
OK,Preference.xml内容已经分析完毕,属性都大致相同,相信亲自动力一试也就那么回事。那么如何把Preference.xml中内容展现出来呢?
Layout是通过继续自Activity的类来进行显示的,前面提到过,PreferenceActivity是专门用于显示preference的,所以只要创建一个继承自PreferenceActivity类即可。代码如下:

public class Setting extends PreferenceActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 所的的值将会自动保存到SharePreferences addPreferencesFromResource(R.xml.preference); } } 接下来就是运行程序,显示劳动成果。至此,工作已经完成大半,所有的值都会保存到SharedPreferences中,我们也可以读取到保存的结果。

2.4如何获取ListPreference中选中的值

研究了一天,貌似ListPreference中根本就没有什么回调函数可以用
于是,向上一层,把注意力集中于SharedPreferences,
发现有这么个接口:onSharedPreferenceChanged
抱着试试看的态度,实现了该接口,发现此方法可行,先将部分代码分享如下:

package yinger.firewall; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; public class CallFireWall extends PreferenceActivity implements OnSharedPreferenceChangeListener { ListPreference lp = null; String whiteMode = "1"; String blackMode = "2"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); this.setTitle("Ying_er" + " Call Safe"); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); lp = (ListPreference) findPreference(getString(R.string.pref_mode_key)); } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { // TODO Auto-generated method stub return super.onPreferenceTreeClick(preferenceScreen, preference); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // TODO Auto-generated method stub System.out.println("onSharedPreferenceChanged"); if (key == getString(R.string.pref_mode_key)){ System.out.println(lp.getValue()); if(lp.getValue().equals(whiteMode)){ } } } }注意:该事件需要注册。既:

prefs.registerOnSharedPreferenceChangeListener(this);

实际上,使用如下方法也是可以得到值的:

PreferenceManager.getDefaultSharedPreferences(context).getBoolean(R.string.pref_mode_key, DEFAULT);

2.5分析Preference事件

★在PreferenceActivity方法中,一个比较重要的监听点击事件方法为:
public booleanonPreferenceTreeClick (PreferenceScreen preferenceScreen, Preference preference)
说 明 : 当Preference控件被点击时,触发该方法。
参数说明: preference 点击的对象。
返回值: true 代表点击事件已成功捕捉,无须执行默认动作或者返回上层调用链。 例如,不跳转至默认Intent。
false 代表执行默认动作并且返回上层调用链。例如,跳转至默认Intent。
在我们继承PreferenceActivity的Activity可以重写该方法,来完成我们对Preference事件的捕捉。
相信通过前面的介绍,你一定知道了如何使用了Preference家族并且对其触发方法。下面我们抛出另外两枚——Preference相关的两个重要监听接口。
★ Preference.OnPreferenceChangeListener 该监听器的一个重要方法如下:
boolean onPreferenceChange(Preference preference,Object objValue)
说明: 当Preference的元素值发送改变时,触发该事件。
返回值:true 代表将新值写入sharedPreference文件中。
false 则不将新值写入sharedPreference文件
★ Preference.OnPreferenceClickListener 该监听器的一个重要方法如下:
public booleanonPreferenceClick(Preference preference)
说明:当点击控件时触发发生,可以做相应操作。
那么当一个Preference控件实现这两个接口时,当被点击或者值发生改变时,触发方法是如何执行的呢?事实上,它的触发规则如下:
1 先调用onPreferenceClick()方法,如果该方法返回true,则不再调用onPreferenceTreeClick方法 ;
如果onPreferenceClick方法返回false,则继续调用onPreferenceTreeClick方法。
2 onPreferenceChange的方法独立与其他两种方法的运行。也就是说,它总是会运行。

2.6 OnPreferenceChangeListener

以上我们分别介绍了Preference对数据的保存及PreferenceActivity设置界面。当PreferenceActivity中的内容改变时,Android系统会自动进行保存和持久化维护,我们只需要在要用的设置界面中数据的地方进行读取就可以了。同时Android还提供了OnPreferenceClickListener和OnPreferenceChangeListener两个与Preference相关的监听接口,当PreferenceActivity中的某一个Preference进行了点击或者改变的操作时,都会回调接口中的函数,这样可以第一个时间向其他Activity等通知系统设置进行了改变。
下面我们以一个具体的Demo说明PreferenceActivity和其监听接口的使用。
新建一个工程AndroidPreferenceDemoII,并按上面的步骤添加xml文件夹和其内容Preferenceii.xml,还有values文件夹中的array.xml和strings.xml。
新建一个名为Settings的class,内容为:

//继承PreferenceActivity,并实现OnPreferenceChangeListener和OnPreferenceClickListener监听接口 public class Settings extends PreferenceActivity implements OnPreferenceChangeListener, OnPreferenceClickListener{ //定义相关变量 String updateSwitchKey; String updateFrequencyKey; CheckBoxPreference updateSwitchCheckPref; ListPreference updateFrequencyListPref; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //从xml文件中添加Preference项 addPreferencesFromResource(R.xml.preferencesii); //获取各个Preference updateSwitchKey = getResources().getString(R.string.auto_update_switch_key); updateFrequencyKey = getResources().getString(R.string.auto_update_frequency_key); updateSwitchCheckPref = (CheckBoxPreference)findPreference(updateSwitchKey); updateFrequencyListPref = (ListPreference)findPreference(updateFrequencyKey); //为各个Preference注册监听接口 updateSwitchCheckPref.setOnPreferenceChangeListener(this); updateSwitchCheckPref.setOnPreferenceClickListener(this); updateFrequencyListPref.setOnPreferenceChangeListener(this); updateFrequencyListPref.setOnPreferenceClickListener(this); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { // TODO Auto-generated method stub Log.v("SystemSetting", "preference is changed"); Log.v("Key_SystemSetting", preference.getKey()); //判断是哪个Preference改变了 if(preference.getKey().equals(updateSwitchKey)) { Log.v("SystemSetting", "checkbox preference is changed"); } else if(preference.getKey().equals(updateFrequencyKey)) { Log.v("SystemSetting", "list preference is changed"); } else { //如果返回false表示不允许被改变 return false; } //返回true表示允许改变 return true; } @Override public boolean onPreferenceClick(Preference preference) { // TODO Auto-generated method stub Log.v("SystemSetting", "preference is clicked"); Log.v("Key_SystemSetting", preference.getKey()); //判断是哪个Preference被点击了 if(preference.getKey().equals(updateSwitchKey)) { Log.v("SystemSetting", "checkbox preference is clicked"); } else if(preference.getKey().equals(updateFrequencyKey)) { Log.v("SystemSetting", "list preference is clicked"); } else { return false; } return true; }

当然重写PreferenceActivity的 onPreferenceTreeClick的方法就可以了,通过参数preference来判断是对那一个元素进行的,并根据需要进行操作。

@Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { return false; }

2.7 OnPreferenceChangeListener与OnPreferenceClickListener的区别

两种监听器OnPreferenceChangeListener和OnPreferenceClickListener,OnPreferenceClickListener的意思好理解,但是OnPreferenceChangeListener就不好懂了,所以就写了个Demo分析了一下,代码如下:

package com.luther.test;  import com.luther.test.R;  import android.content.SharedPreferences; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.widget.Toast;  public class PreferenceDemoActivity extends PreferenceActivity          implements OnPreferenceChangeListener, OnPreferenceClickListener{      private ListPreference mList1Prefs;     private ListPreference mList2Prefs;     private CheckBoxPreference mCheckPrefs;     private EditTextPreference mEditPrefs;     private SharedPreferences mSharedPrefs;          /** Called when the activity is first created. */     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         addPreferencesFromResource(R.xml.preference);         initViews();     }          private void initViews(){         //得到以包命名的SharedPreferences         mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);                  mList1Prefs = (ListPreference) findPreference("key_call_config");         mList2Prefs = (ListPreference) findPreference("key_msg_config");         mCheckPrefs = (CheckBoxPreference) findPreference("switch");         mEditPrefs = (EditTextPreference) findPreference("autoreply_text_cpntent");                  mList1Prefs.setOnPreferenceClickListener(this);         mList1Prefs.setOnPreferenceChangeListener(this);         mList2Prefs.setOnPreferenceChangeListener(this);         mList2Prefs.setOnPreferenceClickListener(this);     }      @Override     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,             Preference preference) {         if(preference == mEditPrefs){             String toastStr = mEditPrefs.getTitle() + "\n"                             + "Content: " + mEditPrefs.getText();             showToast(toastStr);         }         return super.onPreferenceTreeClick(preferenceScreen, preference);     }      public boolean onPreferenceClick(Preference preference) {         String prefsValue = mSharedPrefs.getString(preference.getKey(), "-1");         showToast(prefsValue);         return false;     }      public boolean onPreferenceChange(Preference preference, Object newValue) {                  if(mList1Prefs == preference){             String prefsValue = mSharedPrefs.getString(preference.getKey(), "-1");             showToast(prefsValue);         }         if(mList2Prefs == preference){             String prefsValue = newValue.toString();             showToast(prefsValue);             mList2Prefs.setValue(prefsValue);         }         return false;     }          private void showToast(String arg){         Toast.makeText(this, arg, Toast.LENGTH_SHORT).show();     }       }
程序原理:用一个ListPreference分别注册这两个监听器,然后用Tosat看他们在什么时候响应。
.../res/xml/preference文件如下:

<?xml version="1.0" encoding="utf-8"?> 以下是ListPreference的Entries和EntryValues:
<?xml version="1.0" encoding="utf-8"?> 静音 振动 正常响铃 LED灯亮 0 1 2 3 string.xml文件:

<?xml version="1.0" encoding="utf-8"?> Hello World, PreferenceDemoActivity! PreferenceDemo 设置 常规设置 来电时 来短信时 自定义回复设置 自动回复 自动回复短信 下面是Demo的主界面:


编译好,运行程序:点击mList1Prefs(来电时),Toast显示“-1”。再点击一个选项,对话框消失,Toast显示“-1”,为什么会这样?为什么不是第一次选中时的选项值?
其实,这是因为设置了OnPreferenceChangeListener。默认情况下,普通的ListPreference第一次选中一个值之后,Android框架会存贮好选中的值,下次打开,会默认选中上次选中的值,但是设置OnPreferenceChangeListener之后,值的存储就要自己来了,详见代码中的mList2Prefs.setValue();“来短信时”这一项就能够正常存贮选中的值。
现在区别就出来了:
OnPreferenceClickListener:是响应点击preference的事件,比如程序中,一点ListPreference,onPreferenceClick()中就弹出Toast。
OnPreferenceChangeListener:是响应preference的值被改变的事件(此时被改变的值需要自己存贮到SharedPreferences) ,比如程序中,点击ListPreference的某一项,onPreferenceChange()中就会弹出Toast。
另外:onPreferenceTreeClick()这个方法感觉和OnPreferenceClickListener的回调方法onPreferenceClick()的作用差不多,一样是响应点击的事件。
回头再看OnPreferenceChangeListener的文档:
Interface definition for a callback to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value.
就非常明白了~

   
   
   


更多相关文章

  1. ExpandableListView二级列表
  2. Activity详解 Intent显式跳转和隐式跳转
  3. android shape的使用
  4. webView自适应屏幕大小
  5. Android(安卓)xxx is not translated in yyy, zzz 的解决方法
  6. TextView内容太长怎么办?
  7. android 开发中遇到的问题及解决方法
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. Android报表解决方案 使用开源组件iChart
  2. Android内存溢出与优化(三)——使用完后要c
  3. 用Android线程间通信的Message机制
  4. 【Android】webView 使用 系统自带搜索对
  5. android 解决横竖屏切换时重新载入的问题
  6. Android(安卓)Quantity Strings 的 getQu
  7. Android插件化开发之OpenAtlas插件的安装
  8. Android之百度地图定位最详细使用总结
  9. Android从捕获全局异常说起
  10. android 解析并显示dicom文件的数据和图