android下配置偏好信息的管理

 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函数中这样写:

 

@Override
	protected 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); // recursion
			else
				this.setSummary(p);
		}
	}

	/**
	 * Set the summaries of the given preference
	 */
	private void setSummary(Preference pref) {
		// react on type or key
		if (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方法中添加两行代码:

 

 

@Override
protected 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。

posted @ 2012-03-23 11:09  柒零壹  阅读(707)  评论(0编辑  收藏  举报