Android Preference 须知

Android Preference 须知

一、理论

 

1.前言

在Android的应用开发中经常会涉及到设置界面的设计开发,为此Android提供了名为Preference的设置处理机制,沿用这种机制的话能省去开发者很多不必要的时间开支。

那Preference究竟是什么呢?看一下你Android手机里的“设置”这个应用就知道了,大体界面如下:


这个设置界面就是通过Preference构建的,可能有些同学会说,这不就是一个普通的LinearLayout吗?有什么特别的?下面我们就开具体说说什么是Preference。

 

2.什么是Preference?

Preference翻译过来是“偏爱,爱好”的意思,在Android中Preference是一个具体的类,它代表着一个最基本的UI块(可以理解为ListView中的一个item),并且显示在Activity或Fragment内置的ListView上面,如图1-1中的“声音”选项,就是一个Preference的UI块表现(这里为什么要说表现呢?因为Preference本身并不是继承View的视图类,它只是代表着一个偏好选项然后通过提供UI块来展示这些偏好选项)。并且每一个UI块都会和一个SharePreferences关联来保存或恢复偏好设置。

 

3.Preference从何而来?

得到Preference的方法有两种:一种是从Xml文件中获取,在Xml文件中每一个节点都能指定特定的Preference的子类。另外一种方法就是在代码中动态的创建。为了处理好Preference与SharePreferences的关联,Preference类提供了一个Key来作为使用SharePreferences时的Key。


4.Preference的子类们



开关类型:

TwoStatePreference是一个抽象类,它下面的两个子类CheckBoxPreference和SwitchPreference。

 

弹出框类型:

弹出框类型的都继承子虚拟类DialogPreference,分别是EditPreference,MultiCheckPreference,ListPreference,MultiSelectListPreference,SeekBarDialogPreference,VolumePreferenc。

 

特殊:

RingtonePreference和SeekBarPreference分别是铃声选择和滑块。

 

组类型:

组类型都继承子抽象类PreferenceGroup,其中PreferenceCategory表示分类,PreferenceScreen主要用来表示一个设置界面中的根节点。


5.Preference其他相关类介绍:

GenericInflater:用于解析xml文件

 

PreferenceInflater:继承自GenericInflater用于解析包含Preference的xml

 

PreferenceActivity:在kk和之前的版本上用于显示一系列Preference的Header(标头,用于跳转到对应的PreferenceFragment),从L开始PreferenceActivity的功能被PreferenceFragment集成了。

 

PreferenceFragment:用ListView来显示一系列Preference的层次结构。

 

PreferenceManager:用于帮助从xml或代码中创建Preference的层次结构。


二、实践

 

1.从xml文件中构建Preference ,主要代码如下:

----PreferencesFromXml.java----

[java]  view plain  copy
  1. @Override  
  2.    protected void onCreate(BundlesavedInstanceState) {  
  3.        super.onCreate(savedInstanceState);  
  4.   
  5.        // Load the preferences from an XMLresource  
  6.        //这个方法在L上已经不被提倡使用  
  7.        addPreferencesFromResource(R.xml.preferences);  
  8.    }  

preferences文件内容如下:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--BEGIN_INCLUDE(preferences) -->  
  3. <PreferenceScreen  
  4.        xmlns:android="http://schemas.android.com/apk/res/android">  
  5.    
  6.     <PreferenceCategory  
  7.            android:title="@string/inline_preferences">  
  8.              
  9.         <CheckBoxPreference  
  10.                 android:key="checkbox_preference"  
  11.                 android:title="@string/title_checkbox_preference"  
  12.                 android:summary="@string/summary_checkbox_preference" />  
  13.    
  14.     </PreferenceCategory>  
  15.                  
  16.     <PreferenceCategory  
  17.            android:title="@string/dialog_based_preferences">  
  18.    
  19.         <EditTextPreference  
  20.                 android:key="edittext_preference"  
  21.                 android:title="@string/title_edittext_preference"  
  22.                 android:summary="@string/summary_edittext_preference"  
  23.                 android:dialogTitle="@string/dialog_title_edittext_preference" />  
  24.                  
  25.         <ListPreference  
  26.                 android:key="list_preference"  
  27.                 android:title="@string/title_list_preference"  
  28.                 android:summary="@string/summary_list_preference"  
  29.                 android:entries="@array/entries_list_preference"  
  30.                 android:entryValues="@array/entryvalues_list_preference"  
  31.                 android:dialogTitle="@string/dialog_title_list_preference" />  
  32.    
  33.     </PreferenceCategory>  
  34.    
  35.     <PreferenceCategory  
  36.            android:title="@string/launch_preferences">  
  37.    
  38.         <!-- This PreferenceScreen tag servesas a screen break (similar to page break  
  39.              in word processing). Like forother preference types, we assign a key  
  40.              here so it is able to save andrestore its instance state. -->  
  41.         <PreferenceScreen  
  42.                 android:key="screen_preference"  
  43.                 android:title="@string/title_screen_preference"  
  44.                 android:summary="@string/summary_screen_preference">  
  45.              
  46.             <!-- You can place morepreferences here that will be shown on the next screen. -->  
  47.                       
  48.             <CheckBoxPreference  
  49.                     android:key="next_screen_checkbox_preference"  
  50.                     android:title="@string/title_next_screen_toggle_preference"  
  51.                     android:summary="@string/summary_next_screen_toggle_preference" />  
  52.                  
  53.         </PreferenceScreen>  
  54.    
  55.         <PreferenceScreen  
  56.                 android:title="@string/title_intent_preference"  
  57.                 android:summary="@string/summary_intent_preference">  
  58.    
  59.             <intent android:action="android.intent.action.VIEW"  
  60.                     android:data="http://www.android.com" />  
  61.    
  62.         </PreferenceScreen>  
  63.    
  64.     </PreferenceCategory>  
  65.      
  66.     <PreferenceCategory  
  67.            android:title="@string/preference_attributes">  
  68.      
  69.         <CheckBoxPreference  
  70.                 android:key="parent_checkbox_preference"  
  71.                 android:title="@string/title_parent_preference"  
  72.                 android:summary="@string/summary_parent_preference" />  
  73.    
  74.         <!-- The visual style of a childis defined by this styled theme attribute. -->  
  75.         <CheckBoxPreference  
  76.                 android:key="child_checkbox_preference"  
  77.                 android:dependency="parent_checkbox_preference"  
  78.                 android:layout="?android:attr/preferenceLayoutChild"  
  79.                 android:title="@string/title_child_preference"  
  80.                 android:summary="@string/summary_child_preference" />  
  81.              
  82.     </PreferenceCategory>  
  83.      
  84. </PreferenceScreen>  
  85. <!-- END_INCLUDE(preferences)-->  

 

就是这么简单,只需要简单配置一下xml文件,一个设置界面就完成了,上面的xml文件对应的界面如下:



我们来分析一下这个xml文件

首先看它的根节点 PreferenceScreen 它对应的就是PreferenceScreen对象表示这一层次结构的最外层。接着是PreferenceCategory它表示一个分类的开始对应PreferenceCategory对象。在PreferenceCategory里可以看到一些节点如:CheckBoxPreference,EditTextPreference,ListPreference等,都是表示一个设置选项,其对应的也是名字与之相同的类。

 

2.从代码中构建Preference

代码如下:

----PreferencesFromCode.java----

 

[java]  view plain  copy
  1. public classPreferencesFromCode extends PreferenceActivity {  
  2.    
  3.     private static final StringPARENT_CHECKBOX_PREFERENCE = "parent_checkbox_preference";  
  4.    
  5.     @Override  
  6.     protected void onCreate(BundlesavedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.    
  9.         PreferenceScreen root =getPreferenceManager().createPreferenceScreen(this);  
  10.         setPreferenceScreen(root);  
  11.         populatePreferenceHierarchy(root);  
  12.     }  
  13.    
  14.     private voidpopulatePreferenceHierarchy(PreferenceScreen root) {  
  15.         // Inline preferences  
  16.         PreferenceCategory inlinePrefCat = newPreferenceCategory(this);  
  17.        inlinePrefCat.setTitle(R.string.inline_preferences);  
  18.         root.addPreference(inlinePrefCat);  
  19.    
  20.         // Checkbox preference  
  21.         CheckBoxPreference checkboxPref = newCheckBoxPreference(this);  
  22.         checkboxPref.setKey("checkbox_preference");  
  23.        checkboxPref.setTitle(R.string.title_checkbox_preference);  
  24.        checkboxPref.setSummary(R.string.summary_checkbox_preference);  
  25.        inlinePrefCat.addPreference(checkboxPref);  
  26.    
  27.         // Switch preference  
  28.         SwitchPreference switchPref = newSwitchPreference(this);  
  29.        switchPref.setKey("switch_preference");  
  30.        switchPref.setTitle(R.string.title_switch_preference);  
  31.        switchPref.setSummary(R.string.summary_switch_preference);  
  32.         inlinePrefCat.addPreference(switchPref);  
  33.    
  34.         // Dialog based preferences  
  35.         PreferenceCategory dialogBasedPrefCat =new PreferenceCategory(this);  
  36.        dialogBasedPrefCat.setTitle(R.string.dialog_based_preferences);  
  37.         root.addPreference(dialogBasedPrefCat);  
  38.    
  39.         // Edit text preference  
  40.         EditTextPreference editTextPref = newEditTextPreference(this);  
  41.        editTextPref.setDialogTitle(R.string.dialog_title_edittext_preference);  
  42.        editTextPref.setKey("edittext_preference");  
  43.         editTextPref.setTitle(R.string.title_edittext_preference);  
  44.        editTextPref.setSummary(R.string.summary_edittext_preference);  
  45.        dialogBasedPrefCat.addPreference(editTextPref);  
  46.    
  47.         // List preference  
  48.         ListPreference listPref = newListPreference(this);  
  49.        listPref.setEntries(R.array.entries_list_preference);  
  50.        listPref.setEntryValues(R.array.entryvalues_list_preference);  
  51.        listPref.setDialogTitle(R.string.dialog_title_list_preference);  
  52.         listPref.setKey("list_preference");  
  53.        listPref.setTitle(R.string.title_list_preference);  
  54.        listPref.setSummary(R.string.summary_list_preference);  
  55.        dialogBasedPrefCat.addPreference(listPref);  
  56.    
  57.         // Launch preferences  
  58.         PreferenceCategory launchPrefCat = newPreferenceCategory(this);  
  59.        launchPrefCat.setTitle(R.string.launch_preferences);  
  60.         root.addPreference(launchPrefCat);  
  61.    
  62.         /* 
  63.          * The Preferences screenPref serves asa screen break (similar to page 
  64.          * break in word processing). Like forother preference types, we assign 
  65.          * a key here so that it is able tosave and restore its instance state. 
  66.          */  
  67.         // Screen preference  
  68.         PreferenceScreen screenPref =getPreferenceManager().createPreferenceScreen(this);  
  69.        screenPref.setKey("screen_preference");  
  70.        screenPref.setTitle(R.string.title_screen_preference);  
  71.        screenPref.setSummary(R.string.summary_screen_preference);  
  72.        launchPrefCat.addPreference(screenPref);  
  73.    
  74.         /* 
  75.          * You can add more preferences toscreenPref that will be shown on the 
  76.          * next screen. 
  77.          */  
  78.    
  79.         // Example of next screen togglepreference  
  80.         CheckBoxPreferencenextScreenCheckBoxPref = new CheckBoxPreference(this);  
  81.        nextScreenCheckBoxPref.setKey("next_screen_toggle_preference");  
  82.        nextScreenCheckBoxPref.setTitle(R.string.title_next_screen_toggle_preference);  
  83.        nextScreenCheckBoxPref.setSummary(R.string.summary_next_screen_toggle_preference);  
  84.         screenPref.addPreference(nextScreenCheckBoxPref);  
  85.    
  86.         // Intent preference  
  87.         PreferenceScreen intentPref =getPreferenceManager().createPreferenceScreen(this);  
  88.         intentPref.setIntent(newIntent().setAction(Intent.ACTION_VIEW)  
  89.                .setData(Uri.parse("http://www.android.com")));  
  90.        intentPref.setTitle(R.string.title_intent_preference);  
  91.        intentPref.setSummary(R.string.summary_intent_preference);  
  92.        launchPrefCat.addPreference(intentPref);  
  93.    
  94.         // Preference attributes  
  95.         PreferenceCategory prefAttrsCat = newPreferenceCategory(this);  
  96.        prefAttrsCat.setTitle(R.string.preference_attributes);  
  97.         root.addPreference(prefAttrsCat);  
  98.    
  99.         // Visual parent toggle preference  
  100.         CheckBoxPreference parentCheckBoxPref =new CheckBoxPreference(this);  
  101.        parentCheckBoxPref.setTitle(R.string.title_parent_preference);  
  102.        parentCheckBoxPref.setSummary(R.string.summary_parent_preference);  
  103.         prefAttrsCat.addPreference(parentCheckBoxPref);  
  104.        parentCheckBoxPref.setKey(PARENT_CHECKBOX_PREFERENCE);  
  105.    
  106.         // Visual child toggle preference  
  107.         // See res/values/attrs.xml for the<declare-styleable> that defines  
  108.         // TogglePrefAttrs.  
  109.         TypedArray a = obtainStyledAttributes(R.styleable.TogglePrefAttrs);  
  110.         CheckBoxPreference childCheckBoxPref =new CheckBoxPreference(this);  
  111.        childCheckBoxPref.setTitle(R.string.title_child_preference);  
  112.        childCheckBoxPref.setSummary(R.string.summary_child_preference);  
  113.         childCheckBoxPref.setLayoutResource(  
  114.                a.getResourceId(R.styleable.TogglePrefAttrs_android_preferenceLayoutChild,  
  115.                         0));  
  116.        prefAttrsCat.addPreference(childCheckBoxPref);  
  117.         childCheckBoxPref.setDependency(PARENT_CHECKBOX_PREFERENCE);  
  118.         a.recycle();  
  119.     }  
  120. }  

 

动态构建Preference的过程是:构建PreferenceScreen,然后构建PreferenceCategory,并往PreferenceCategory中添加需要使用的Preference的子类,然后将PreferenceCategory添加到PreferenceScreen。

上述代码效果图如下:



三、Preference实现机制

 

在讲机制之前我们来做一个简单的demo,通过这个demo来直击Preference的运行现场。

 

demo很简单,有两个界面:

MyPreferenceDemo.java (一个activity,显示从SharePreferences取key为my_demo_key的值)

MySetting.java (一个key为my_demo_key的EditPreference)

关键代码如下:

----MyPreferenceDemo.java

[java]  view plain  copy
  1. public class MyPreferenceDemo extends Activity {  
  2.    
  3.     private TextView mTextView ;  
  4.     @Override  
  5.     protected void onCreate(BundlesavedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(R.layout.activity_main);  
  8.         mTextView = (TextView)findViewById(R.id.show_preferecne) ;  
  9.     }  
  10.    
  11.     @Override  
  12.     protected void onResume() {  
  13.         super.onResume();  
  14.         mTextView.setText(getPreferenceByKey());  
  15.     }  
  16.    
  17.     private String getPreferenceByKey() {  
  18.          
  19.         String pref = "" ;  
  20.         pref =PreferenceManager.getDefaultSharedPreferences(this).getString("my_demo_key","Hello") ;  
  21.         return pref;  
  22.     }  
  23.    
  24.     @Override  
  25.     public boolean onCreateOptionsMenu(Menu menu){  
  26.         // Inflate the menu; this adds itemsto the action bar if it is present.  
  27.         getMenuInflater().inflate(R.menu.main, menu);  
  28.         return true;  
  29.     }  
  30.    
  31.     @Override  
  32.     public boolean onOptionsItemSelected(MenuItemitem) {  
  33.         if(item.getItemId() == R.id.action_settings){  
  34.             Toast.makeText(this"settings", Toast.LENGTH_LONG).show() ;  
  35.             Intent intent = new Intent() ;  
  36.             intent.setClass(this, MySetting.class) ;  
  37.             startActivity(intent) ;  
  38.         }  
  39.         return super.onOptionsItemSelected(item);  
  40.     }  
  41. }  


 

----MySetting.java

[java]  view plain  copy
  1. public class MySetting extends PreferenceActivity {  
  2.    
  3.     @Override  
  4.     protected void onCreate(BundlesavedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.          
  7.         PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);  
  8.         setPreferenceScreen(root);  
  9.         populatePreferenceHierarchy(root);  
  10.     }  
  11.      
  12.     private void populatePreferenceHierarchy(PreferenceScreenroot) {  
  13.         PreferenceCategory myCat = new PreferenceCategory(this);  
  14.         myCat.setTitle("My PreferenceDemo");  
  15.         root.addPreference(myCat);  
  16.    
  17.         EditTextPreference editTextPref = new EditTextPreference(this);  
  18.         editTextPref.setDialogTitle("please inputsomething");  
  19.         editTextPref.setKey("my_demo_key");  
  20.         editTextPref.setTitle("settings");  
  21.         editTextPref.setSummary("设置activity中需要显示的字符串");  
  22.         myCat.addPreference(editTextPref);  
  23.    
  24.     }  
  25. }  


 

程序界面如下:

    


点击“settings”输入“这是preference的demo”,然后返回第一个界面,就会显示 “这是preference的demo”。

 

我们先来看看获得SharePreferences的这个方法:

 

[java]  view plain  copy
  1. PreferenceManager.getDefaultSharedPreferences(this)  


跟进源代码发现getDefaultSharedPreferences的实现如下:

[java]  view plain  copy
  1. public static SharedPreferencesgetDefaultSharedPreferences(Context context)      {  
  2.     returncontext.getSharedPreferences(getDefaultSharedPreferencesName(context),  
  3.            getDefaultSharedPreferencesMode());  
  4. }  
  5.   
  6. private static StringgetDefaultSharedPreferencesName(Context context) {  
  7.     return context.getPackageName() + "_preferences";  
  8. }  
  9.   
  10. private static intgetDefaultSharedPreferencesMode() {  
  11.     return Context.MODE_PRIVATE;  
  12. }  

内部其实还是调用了 getSharedPreferences这个方法来获得SharePreferences,参数name和mode分别是:context.getPackageName() +"_preferences" Context.MODE_PRIVATE

 

接着我们看看我们使用的 EditTextPreference是怎么将字符串保存到SharePreferences的,

 

我们看到在EditTextPreference内部有这么一个回调方法:

 

  

[java]  view plain  copy
  1. @Override  
  2.    protected void onDialogClosed(boolean positiveResult) {  
  3.        super.onDialogClosed(positiveResult);  
  4.         
  5.        if (positiveResult) {  
  6.            String value = mEditText.getText().toString();  
  7.            if (callChangeListener(value)) {  
  8.                setText(value);  
  9.            }  
  10.        }  
  11.    }  

 

当设置好字符串关闭对话框时这个方法会被回调,获得输入的字符串value然后调用settext(value),

 

   

[java]  view plain  copy
  1. public void setText(String text) {  
  2.        final boolean wasBlocking =shouldDisableDependents();  
  3.         
  4.        mText = text;  
  5.         
  6.        persistString(text);  
  7.         
  8.        final boolean isBlocking =shouldDisableDependents();  
  9.        if (isBlocking != wasBlocking) {  
  10.            notifyDependencyChange(isBlocking);  
  11.        }  
  12.    }  

 

我们接着看persistString(text);  这个方法,首先persist的意思是持久化,那我们可以很容易联想到本地文件或者数据库之类的,那这边到底会把text保存到哪里?我们接着看。

 

 

[java]  view plain  copy
  1. protected boolean persistString(String value) {  
  2.      if (shouldPersist()) {  
  3.          // Shouldn't store null  
  4.          if (value == getPersistedString(null)) {  
  5.              // It's already there, so the sameas persisting  
  6.              return true;  
  7.          }  
  8.           
  9.          SharedPreferences.Editor editor = mPreferenceManager.getEditor();  
  10.          editor.putString(mKey, value);  
  11.          tryCommit(editor);  
  12.          return true;  
  13.      }  
  14.      return false;  
  15.  }  

 

看到这里就就明了了,最终还是将value这个数据保存在了SharePreferences里面。

 

最基本的Preference实现机制就到这里了,总结一句话:

Preference设置属性的保存还是依赖于SharePreferences

关于SharePreferences的运行机制,我会在后面在给出。


pdf下载 http://pan.baidu.com/s/1o6p2dYi


原文地址:http://blog.csdn.net/will_captain/article/details/40404523

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值