android下配置偏好信息的管理

来源:互联网 发布:unity3d怎么模拟场景 编辑:程序博客网 时间:2024/04/28 23:55

 android下配置偏好信息的管理

佣工7001

       应用程序一般都有这样的需求,为了应用有更好的适应性,有一些参数设置需要独立出来放在配置文件里面。这个配置文件应该是开发的时候就编辑好的设好了默认值,安装后应该可以让用户修改一些设置并保存。程序运行的时候读取这些设置并根据设置不同进行不同的操作。比如windows下程序惯用的INI文件,如果是j2ee项目我们会使用property文件来保存这些参数,那么在android下面如何实现呢?在android中提供了SharedPreference这个类来配置参数设置,书上网上很多例子都是用程序对SharedPreference的读写操作,可是怎样拥有初始设置的值呢?当然可以自己读取资源中的xml文件,然后手动写程序保存到SharedPreference中,可这样太麻烦了一点都不方便、不专业。

        经过我的一番搜索研究,发现最好的方法就是使用Preference管理设置,android sdk已内置了良好的支持,所有的功能都在android.preference这个命名空间中。经学习发现这个preference的管理是和SharedPreference结合实现的,完美的实现了我的需求,并且是实现了和android系统设置中一样的设置管理界面,显得很专业微笑。闲言少叙,下面就具体来看如何使用preference实现配置功能。

        一、建立配置文件。

        在项目res目录下xml目录下(如果没有请建立)建立一个settings.xml的xml文件(文件名不一定叫settings,但是一定要放在xml目录下),文件内容如下:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"    android:title="Settings" >    <PreferenceCategory android:key="general" android:title="基本设置"><ListPreference android:key="superman" android:entries="@array/choice"  android:entryValues="@array/choiceId"     android:dialogTitle="我的最爱" android:summary=""    android:defaultValue="value5" android:title="你选哪个"/>    <CheckBoxPreference android:key="bigman" android:title="我要做大英雄"            android:defaultValue="true"            android:summaryOn="唯大英雄能本色,是真名士自风流" android:summaryOff="请君暂上凌烟阁,若个书生万户侯"/><EditTextPreference            android:defaultValue="宁可我负天下人,不可天下人负我!"            android:key="maxim"            android:summary="有了信仰就要干,不要无志者常立志"            android:title="我最爱的格言" />          <EditTextPreference            android:defaultValue="星球大战"            android:key="favoriteFilm"            android:summary="没有最好,只有更好"            android:title="我最爱的电影" />     </PreferenceCategory>    <PreferenceCategory android:key="advanced" android:title="高级设置">    <PreferenceScreen android:key="basicSettings" android:title="高级设置" android:summary="点击进入高级设置" >        <CheckBoxPreference android:key="checkVersion" android:title="自动更新"            android:defaultValue="false"            android:summaryOn="程序将每隔一段时间自动检查新版本" android:summaryOff="自动更新已关闭"/>        <EditTextPreference            android:defaultValue="1"            android:key="checkVersionTime"            android:summary=""            android:title="检查新版本间隔时间(天)" />        <EditTextPreference            android:defaultValue="http://192.168.0.99:8008/crx/xtgl.User"            android:key="url"            android:summary=""            android:title="URL" />        <EditTextPreference            android:defaultValue="http://60.29.99.76:8008/crx/xtgl.Unit?__fn_=initdata"            android:key="url1"            android:summary=""            android:title="URL2" />        <EditTextPreference            android:defaultValue="htt2.p://192.168.0.100:8558/crx/manage.HistVote"            android:key="URL3"            android:summary=""            android:title="URL3" />            </PreferenceScreen></PreferenceCategory></PreferenceScreen>


         文件的根元素就是PreferenceScreen,望文生义,就是一个屏幕显示的配置内容,并且可以嵌套使用。PreferenceScreen下面还可以分类,这就是PreferenceCategory元素,并且PreferenceCategory元素下面同样可以嵌套PreferenceScreen元素(其实PreferenceScreen就是PreferenceCategory的子类)。详细的配置内容可用的元素有EditTextPreference,CheckBoxPreference,ListPreference,Preference,RingtongPreference......

        从上面的配置文件中可以看出一个Preference配置项目主要拥有的属性。其中Key为这个PreferenceID,设置了才可以在代码中引用,Title是显示的标题,Summary是显示在标题下的文字介绍,Dependency是指依赖的其他配置项(注:一般在Dependency中填写一个CheckBoxPreferenceKey,这样就会在填写的那个CheckBoxPreference勾选时当前这个Preference才可用),Default Value为初始值,等等。其他的请大家自己看sdk,在这里就不赘述了。

        值得一提的就是ListPreference的使用稍微复杂一些,ListPreference除了继承自Preference的属性外,还有自己ListPreference的属性和继承自DialogPreference的属性。其中属于ListPreference的属性有两个:Entries填的为一个字符串数组,是列表显示出来的值(用户看到的说明文字),而Entry Values是实际要保存的值对应的字符串数组。DialogPreference只要填一个Dialog title标题和一个取消按钮显示的字即可。下面建立两个String array供ListPreference的选择对话框使用,在res/values目录下建立一个新的myarrays.xml文件(文件名随便),内容如下.

<?xml version="1.0" encoding="utf-8"?><resources>    <string-array name="choice">        <item >超人</item>        <item >蜘蛛侠</item>        <item >夜魔侠</item>        <item >青蜂侠</item>        <item >蝙蝠侠</item>        <item >闪电侠</item>        <item >钢铁侠</item>        <item >超胆侠</item>        <item >绿灯侠</item>    </string-array>    <string-array name="choiceId">        <item >value1</item>        <item >value2</item>        <item >value3</item>        <item >value4</item>        <item >value5</item>        <item >value6</item>        <item >value7</item>        <item >value8</item>        <item >value9</item>    </string-array>    </resources>
好了,我们的前期准备已经搞定了。

       二、读取配置内容。

       配置信息已经建好了,下面就是读取了,怎么读取呢?看到网上的解决方法很简单,就是得到默认的SharedPreference,然后按照Preference的key值读取,好的,马上试验:在Activity中添加一个按钮BtnTestConfig,设置OnClick事件如下:

OnClickListener onBtnTestConfig = new OnClickListener() {public void onClick(View v) {String s = "not read!";IndexActivity me = IndexActivity.this;SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(me);try {s = sp.getString("favoriteFilm", s);} catch (Exception e) {e.printStackTrace();}DialogUtil.ShowMsgDlg(IndexActivity.this, String.valueOf(s));}};
可是一运行发现,显示的是程序中给出的默认值,根本不是配置写的“星球大战”!咋回事儿呢,老办法google一下,发现有说要用XmlResourceParser自己解析XML,可是这就有违初衷了!不行再搜,终于在老外哪里找到了,原来android不会自动将你的Preference配置同步到SharedPreference中,所以需要用到PreferenceManager.setDefaultValues(Context context, int resId, boolean readAgain)方法,修改程序如下:

OnClickListener onBtnTestConfig = new OnClickListener() {public void onClick(View v) {String s = "not read!";IndexActivity me = IndexActivity.this;PreferenceManager.setDefaultValues(IndexActivity.this, R.xml.settings, true);SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(me);try {s = sp.getString("favoriteFilm", s);} catch (Exception e) {e.printStackTrace();}DialogUtil.ShowMsgDlg(IndexActivity.this, String.valueOf(s));}};
再次运行,ok,终于读到了!这里注意PreferenceManager.setDefaultValues方法的第三个参数readAgain,false表示只会执行一次,也就是说SharedPreference已经同步过一次,此函数就不会再执行了,这样如果在调试阶段你会发现新增加的配置项目就读不到了(打开设置界面编辑后是可以的),所以调试时最好用true。当然这里只是试验,在实际程序中,最好放在主Activity中执行这个函数。另外,readAgain设为true,不会覆盖已经存在于SharedPreference中的配置值,不会造成用户修改的配置丢失。

注意,如果你想清除修改的配置,那么在你要这样

PreferenceManager.getDefaultSharedPreferences(Context context),之后调用PreferenceManager.setDefaultValues(Context context, int resId, boolean readAgain),并且readAgain设为true)
       三、实现配置管理界面。

       到现在,Preference已经建立好并且可以读取了,那么怎么实现用户修改Preference设置呢?这个就更简单了,新建立一个Activity并继承PreferenceActivity,

public class MyPreference extends PreferenceActivity

然后再onCreate函数中这样写:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.addPreferencesFromResource(R.xml.settings);}
然后要做的就是在主界面中添加菜单或按钮调用这个Activity(这个就赘述了),怎么样,是不是和系统的设置界面一样漂亮。


         四、更完美的设置界面。

         试了试,搞好的Preference界面,忽然发现了还有一个缺点,每个配置项目下面的Summary信息都是固定的,如果能够显示用户的当前设置那就完美了。废话少说还是网上学习去,过程不必细说,结果发现还真没有方便的手段可用。没办法,只能程序代码实现。所用技术就是Perference.setSummary这个函数。思想就是在初始化的时候,更据当前配置内容,遍历配置项设置summary内容,然后注册SharedPreference的OnSharedPreferenceChangeListener事件监听配置项的变化,随时更新已变化项目的summary信息。

        由于需要注册OnSharedPreferenceChangeListener事件,所以我们的Activity还要实现OnSharedPreferenceChangeListener这个接口。

public class MyPreference extends PreferenceActivity implements OnSharedPreferenceChangeListener {
        然后添加三个方法:

/** * Set the summaries of all preferences */private void initSummaries(PreferenceGroup pg) {for (int i = 0; i < pg.getPreferenceCount(); ++i) {Preference p = pg.getPreference(i);if (p instanceof PreferenceGroup)this.initSummaries((PreferenceGroup) p); // recursionelsethis.setSummary(p);}}/** * Set the summaries of the given preference */private void setSummary(Preference pref) {// react on type or keyif (pref instanceof ListPreference) {ListPreference listPref = (ListPreference) pref;listPref.setSummary(listPref.getEntry());}if (pref instanceof EditTextPreference) {EditTextPreference etp = (EditTextPreference) pref;etp.setSummary(etp.getText());}}/** * used to change the summary of a preference */public void onSharedPreferenceChanged(SharedPreferences sp, String key) {Toast.makeText(this, "preference changed! " + key, 3000);Preference pref = findPreference(key);this.setSummary(pref);}

      最后在onCrate方法中添加两行代码:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.addPreferencesFromResource(R.xml.settings);this.getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);      this.initSummaries(this.getPreferenceScreen());}
ok,打完收工,运行起来再看效果:


怎么样,堪称完美吧。吐舌头下面试试我们的ListPreference,选择一个新的英雄:

选择完成后,再看Preference管理界面,提示信息已变为“夜魔侠”一切ok。

	
				
		
原创粉丝点击