免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
從零開始

第5章 設(shè)置(Settings)


本章不同于通常網(wǎng)絡(luò)上經(jīng)常使用的SharedPreference,而是從底層了解Preference。FAQ QQ群213821767


應(yīng)用程序通常包括允許用戶修改應(yīng)用程序的特性和行為的設(shè)置功能。例如,一些應(yīng)用程序允許用戶指定通知是否啟用或指定多久使用云同步數(shù)據(jù)。如果你想要為你的應(yīng)用程序提供設(shè)置,你應(yīng)該使用Android的Preference APIs來構(gòu)建統(tǒng)一的接口。本章的主角就是Preference,下面先讓我們看一下圖5-1:


:


圖5-1 這是android短信息應(yīng)用程序的設(shè)置界面截圖。它使用就是就是Preference


5.1 概述


相比使用View對象來構(gòu)建用戶接main,設(shè)置是構(gòu)建Preference的子類。一個(gè)Preference對象是構(gòu)建一個(gè)單一設(shè)置的一個(gè)部分。每一個(gè)Preference作為一個(gè)item在list并為用戶修改設(shè)置提供了適當(dāng)?shù)慕缑妗@?,一個(gè)CheckBoxPreference創(chuàng)建一個(gè)用于顯示checkbox的list item,ListPreference創(chuàng)建一個(gè)選擇列表來顯示一個(gè)對話框的item。每一個(gè)Preference其實(shí)都以鍵值對的形式保存在你應(yīng)用程序的SharedPreferences文件中。當(dāng)用戶改變設(shè)置時(shí),系統(tǒng)會更新SharedPreferences文件中的鍵值對。我們只需要讀取文件中的設(shè)置數(shù)據(jù)即可。SharedPreferences支持以下數(shù)據(jù)類型的保存:


Boolean


Float


Int


Long


String


String Set


因?yàn)槟愕膽?yīng)用程序設(shè)置界面是使用Preference對象構(gòu)建的而不是view,你需要使用Activity或Fragment的子類來顯示設(shè)置列表:


◆    如果你的應(yīng)用程序支持android 3.0以下版本,你必須使用PreferenceActivity類來構(gòu)建。


◆    如果高于或等于android 3.0版本,你可以使用PreferenceFragment。當(dāng)然你屏幕如果足夠大的話你還是可以使用PreferenceActivity創(chuàng)建雙面板布局來顯示多組設(shè)置


5.1.1 Preference


你應(yīng)用中的每一個(gè)設(shè)置都代表一個(gè)Preference對象。每一個(gè)Preference的子類包含一組核心的屬性,如允許你指定設(shè)置的標(biāo)題和默認(rèn)值這樣的屬性。每一個(gè)子類也提供自己的屬性和用戶界面。就想上面圖5-1那樣,每一個(gè)設(shè)置都是List View中的一個(gè)item,也是一個(gè)Preference對象。常見的Preference如下:


CheckBoxPreference


用checkbox顯示一個(gè)item的設(shè)置是否為打開或關(guān)閉。他保存的是boolean值,true表示選中


ListPreference


以單選按鈕列表的形式打開一個(gè)對話框,保存的值能支持任意類型


EditTextPreference


使用EditText打開一個(gè)對話框。保存的值為一個(gè)String。


5.2 在XML中定義Preferences


雖然你可以在運(yùn)行時(shí)實(shí)例化新的Preference對象,但你也可以在XML中用Preference層級對象來定義。使用XML定義設(shè)置是首選,因?yàn)閄ML文件結(jié)構(gòu)更容易閱讀的并且更新也很簡單。此外,你的應(yīng)用程序的設(shè)置通常是預(yù)先確定的,但你仍然可以在運(yùn)行時(shí)修改它們。每一個(gè)Preference子類都能使用XML節(jié)點(diǎn)來匹配聲明。如<CheckBoxPreference>。你必須在項(xiàng)目的res/xml目錄下保存這種XML文件。盡管你可以任意命名你的文件名字,但建議使用preferences.xml,方便以后識別自己寫的東西。注意如果你想要為你的設(shè)置創(chuàng)建多面板布局,那你需要為每一個(gè)fragment創(chuàng)建單獨(dú)的XML文件。


根節(jié)點(diǎn)的XML文件必須是一個(gè)< PreferenceScreen >元素。在這個(gè)元素中你可以添加每個(gè)Preference。每個(gè)你添加在< PreferenceScreen >元素下的子節(jié)點(diǎn)顯示為單一列表項(xiàng)的設(shè)置。如代碼清單5-1所示:



按 Ctrl+C 復(fù)制代碼
按 Ctrl+C 復(fù)制代碼

 



代碼清單5-1


在上面的例子中有一個(gè)CheckBoxPreference和一個(gè)ListPreference。這兩個(gè)items包含以下三個(gè)屬性:


◆android:key


這個(gè)屬性是必須的,對于一個(gè)preferences 來說是一個(gè)持久的數(shù)據(jù)值。當(dāng)在SharedPreferences中保存這個(gè)Setting值時(shí)這個(gè)指定唯一的key(一個(gè)字符串)是被系統(tǒng)使用的。但某些特殊情況,如preferences是一個(gè)PreferenceCategory或 PreferenceScreen,或者是一個(gè)XML中<Intent>調(diào)用時(shí),又或者是一個(gè)Fragment顯示時(shí)(用android:fragment屬性),以上這些特殊情況下,這個(gè)key就不是必須的了。


◆android:title


為設(shè)置提供了一個(gè)用戶可見的名稱。


◆android:defaultValue


這指定初始值,系統(tǒng)應(yīng)該建立在SharedPreferences文件。你應(yīng)該為所有設(shè)置提供一個(gè)默認(rèn)值。


關(guān)于其他更多屬性,請直接查看Preference文檔。


 


圖 5-2 根據(jù)title的設(shè)置分類

1. 通過指定<PreferenceCategory>節(jié)點(diǎn)的分類 

2. 通過使用android:title指定title分類.


當(dāng)你的列表設(shè)置超過大約10項(xiàng),您可能想通過添加標(biāo)題定義分組設(shè)置或在一個(gè)單獨(dú)的屏幕顯示這些組。


5.2.1創(chuàng)建設(shè)置組(groups)


如果你列出10個(gè)或更多的設(shè)置,用戶可能會有些頭疼。這樣我們就可以使用分組。以下有兩種分組方法:


◆使用titles


◆使用subscreens


1. 使用titles


如果你想要根據(jù)標(biāo)題來提供分界線,請使用PreferenceCategory如代碼清單5-2所示:




<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">    <PreferenceCategory         android:title="@string/pref_sms_storage_title"        android:key="pref_key_storage_settings">        <CheckBoxPreference            android:key="pref_key_auto_delete"            android:summary="@string/pref_summary_auto_delete"            android:title="@string/pref_title_auto_delete"            android:defaultValue="false"... />        <Preference             android:key="pref_key_sms_delete_limit"            android:dependency="pref_key_auto_delete"            android:summary="@string/pref_summary_delete_limit"            android:title="@string/pref_title_sms_delete"... />        <Preference             android:key="pref_key_mms_delete_limit"            android:dependency="pref_key_auto_delete"            android:summary="@string/pref_summary_delete_limit"            android:title="@string/pref_title_mms_delete" ... />    </PreferenceCategory>    ...</PreferenceScreen>


 



代碼清單5-2


2. 使用subscreens


 


如果你想要放置設(shè)置組到一個(gè)subscreen中,請使用PreferenceScreen如圖5-3和代碼清單5-3:



 


圖 5-3




<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">    <!--打開一個(gè)subscreen -->    <PreferenceScreen        android:key="button_voicemail_category_key"        android:title="@string/voicemail"        android:persistent="false">        <ListPreference            android:key="button_voicemail_provider_key"            android:title="@string/voicemail_provider" ... />        <!--打開另一個(gè)嵌套的subscreen -->        <PreferenceScreen            android:key="button_voicemail_setting_key"            android:title="@string/voicemail_settings"            android:persistent="false">            ...        </PreferenceScreen>        <RingtonePreference            android:key="button_voicemail_ringtone_key"            android:title="@string/voicemail_ringtone_title"            android:ringtoneType="notification" ... />        ...    </PreferenceScreen>    ...</PreferenceScreen>


 



代碼清單5-3


5.2.2使用Intents


某些情況下, 你可能想要一個(gè)preference item來打開不同的activity而不是設(shè)置屏幕,就像一個(gè)web瀏覽器來查看一個(gè)web頁面。當(dāng)用戶選擇一個(gè)preference item時(shí)可以調(diào)用Intent來啟動。方法就是添加一個(gè)<intent>節(jié)點(diǎn)到<Preference>節(jié)點(diǎn)中。如代碼清單5-4所示:




<Preference android:title="@string/prefs_web_page" >    <intent android:action="android.intent.action.VIEW"            android:data="http://www.example.com" /></Preference>


 



代碼清單5-4


 


你能使用以下屬性創(chuàng)建隱式和顯式的intents:


android:action


如同setAction()方法一樣設(shè)置action


android:data


如同setData()方法一樣設(shè)置data


◆android:mimeType


如同setType()方法一樣設(shè)置MIME類型


◆android:targetClass


如同setComponent()方法一樣設(shè)置組件類名


◆android:targetPackage


如同setComponent()方法一樣設(shè)置組件包名


5.3 創(chuàng)建一個(gè)Preference Activity


為了在Acitivity中顯示你的設(shè)置,你可以繼承PreferenceActivity類。這是擴(kuò)展于傳統(tǒng)Activity的一個(gè)類,它基于Preference對象層級來顯示一個(gè)設(shè)置列表。當(dāng)用戶做出一個(gè)改變時(shí)PreferenceActivity能自動保存與每一個(gè)Preference相關(guān)的設(shè)置。注意:如果在3.0或以上系統(tǒng)版本中,你應(yīng)該使用PreferenceFragment。最重要的是要記住,你在onCreate()回調(diào)期間沒有加載一個(gè)視圖的布局。而是調(diào)用addPreferencesFromResource()來添加你定義的XML文件。例如代碼清單5-5所示:




public class SettingsActivity extends PreferenceActivity {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        addPreferencesFromResource(R.xml.preferences);    }}


 



代碼清單5-5


只要用戶修改preference,系統(tǒng)將改變保存到一個(gè)默認(rèn)的SharedPreferences文件。


5.4 使用Preference Fragments


如果你在android3.0或更高版本上開發(fā),你應(yīng)該使用PreferenceFragment來顯示Preference  對象列表。你不應(yīng)該在使用PreferenceActivity了。因?yàn)镕ragments提供更為靈活的應(yīng)用程序結(jié)構(gòu)如代碼清單5-6所示:




public static class SettingsFragment extends PreferenceFragment {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        addPreferencesFromResource(R.xml.preferences);    }    ...}


 



代碼清單5-6


然后你能吧這個(gè)fragment添加到Activity,如代碼清單5-7所示:




public class SettingsActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getFragmentManager().beginTransaction()                .replace(android.R.id.content, new SettingsFragment())                .commit();    }}


 



代碼清單5-7


注意:一個(gè)PreferenceFragment沒有它自己的Context對象。如果你需要一個(gè)Content對象,你能調(diào)用getActivity()方法。然而,當(dāng)fragment沒有附加到activity中或者activity聲明周期結(jié)束時(shí)分離后,你使用getActivity()返回的將是null。


5.5 Setting的默認(rèn)值


    你創(chuàng)建preferences可能是為你的應(yīng)用程序定義一些重要的行為,所以當(dāng)用戶第一次打開你的應(yīng)用程序時(shí),為每一個(gè)Preference相關(guān)的SharedPreferences 文件初始化默認(rèn)值是必要的。首先你必須為每一個(gè)Preference對象指定一個(gè)默認(rèn)值,你可以在XML文件中使用android:defaultValue屬性。例如代碼清單5-8所示:



按 Ctrl+C 復(fù)制代碼
按 Ctrl+C 復(fù)制代碼

 



代碼清單5-8


然后,在Main Activity里的onCreate()方法中調(diào)用一次setDefaultValues(),如代碼清單5-9所示:




PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);


 



代碼清單5-9


在onCreate()方法的最開始就可以執(zhí)行此方法,因?yàn)榭赡苣愕慕缑嫘枰罁?jù)默認(rèn)值來設(shè)置一個(gè)屬性。這個(gè)方法中有三個(gè)參數(shù):


1.應(yīng)用程序的Context


2.Preference XML資源ID


3.這個(gè)boolean表示是否多次設(shè)置默認(rèn)值,當(dāng)然大部分情況下默認(rèn)值一般我們只需要設(shè)置一次,就傳false即可


5.6 使用Preference Headers


在少數(shù)情況下,如用首次屏幕顯示的時(shí)候,你可能想要讓用戶先設(shè)置一些配置屬性。在android3.0或更高版本系統(tǒng)下,你可以使用新的“headers”功能來代替以前的subscreens的嵌套。使用headers步驟如下:


1. 單獨(dú)的每組設(shè)置作為獨(dú)立PreferenceFragment的實(shí)例。即,每組設(shè)置需要一個(gè)單獨(dú)的XML文件。


2. 創(chuàng)建一個(gè)XML頭文件,其中列出了每個(gè)設(shè)置組和聲明這fragment包含相應(yīng)的設(shè)置列表。


3. 擴(kuò)展PreferenceActivity類來托管您的設(shè)置。


4. 實(shí)現(xiàn)onBuildHeaders()回調(diào)用來指定頭文件。


一個(gè)很棒的好處是,PreferenceActivity使用這個(gè)設(shè)計(jì)自動給出了雙欄布局如圖5-4大屏幕上運(yùn)行時(shí)。


即使你的應(yīng)用程序支持Android 3.0以上的版本,你也可以使用PreferenceFragment來構(gòu)建應(yīng)用程序用于較新的設(shè)備


 


圖 5-4 使用headers的雙面板布局


1. headers使用一個(gè)xml heanders文件定義


2.每一組設(shè)置通過PreferenceFragment來定義,并且在<header>節(jié)點(diǎn)中指定


 


圖 5-5 這是一個(gè)手機(jī)設(shè)備,當(dāng)一個(gè)item選中時(shí)候,會調(diào)用PreferenceFragment


5.6.1創(chuàng)建headers文件


每一組設(shè)置你都可以在<preference-headers>跟節(jié)點(diǎn)中指定一個(gè)<header>節(jié)點(diǎn),如代碼清單5-10所示:




<?xml version="1.0" encoding="utf-8"?><preference-headers xmlns:android="http://schemas.android.com/apk/res/android">    <header         android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"        android:title="@string/prefs_category_one"        android:summary="@string/prefs_summ_category_one" />    <header         android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"        android:title="@string/prefs_category_two"        android:summary="@string/prefs_summ_category_two" >        <!—這個(gè)鍵值對可以當(dāng)成一個(gè)fragment的參數(shù)-->        <extra android:name="someKey" android:value="someHeaderValue" />    </header></preference-headers>


 



代碼清單5-10


使用android:fragment屬性,每一個(gè)header聲明一個(gè)PreferenceFragment實(shí)例,當(dāng)用戶選擇這個(gè)header時(shí)就會打開這個(gè)PreferenceFragment。<extras>節(jié)點(diǎn)允許你通過鍵值對的形式傳參,一般是使用Bundle。Fragment通過調(diào)用getArguments()來得到參數(shù)。關(guān)于參數(shù)的用途比較常見的就是為每一個(gè)組重用相同的PreferenceFragment子類并且使用參數(shù)還是制定你將要載入哪一個(gè)preferences XML文件。例如,下面是一個(gè)fragment,它被多個(gè)設(shè)置組重用,下面代碼清單5-11中在XML中使用了<extra>節(jié)點(diǎn),key為“settings”:




public static class SettingsFragment extends PreferenceFragment {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);         String settings = getArguments().getString("settings");        if ("notifications".equals(settings)) {            addPreferencesFromResource(R.xml.settings_wifi);        } else if ("sync".equals(settings)) {            addPreferencesFromResource(R.xml.settings_sync);        }    }}


 



代碼清單5-11


5.6.2顯示headers


為了顯示preference headers, 你必須實(shí)現(xiàn)onBuildHeaders()回調(diào)方法并且調(diào)用loadHeadersFromResource()如代碼清單5-12所示:




public class SettingsActivity extends PreferenceActivity {    @Override    public void onBuildHeaders(List<Header> target) {        loadHeadersFromResource(R.xml.preference_headers, target);    }}


 



代碼清單5-12


當(dāng)用戶從headers列表中選擇一個(gè)item時(shí),系統(tǒng)會打開相關(guān)的PreferenceFragment。注意當(dāng)使用preference headers時(shí)候,你的PreferenceActivity 子類不需要onCreate()方法,因?yàn)檫@個(gè)activity的任務(wù)僅僅是載入headers而已。


5.6.3老版本中支持Preference header


如果你的應(yīng)用程序既支持3.0以下的版本,也支持3.0以上的版本,要么3.0以上我們使用headers能提供雙面板布局。低于3.0的版本我們就可以添加額外的preferences XML但里面不是使用<header>而是使用<Preference>節(jié)點(diǎn)了。但每一個(gè)<Preference>都發(fā)送一個(gè)intent到PreferenceActivity。例如讓我們先看下3.0或以上版本的代碼清單5-13中(res/xml/preference_headers.xml):




<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">    <header         android:fragment="com.example.prefs.SettingsFragmentOne"        android:title="@string/prefs_category_one"        android:summary="@string/prefs_summ_category_one" />    <header         android:fragment="com.example.prefs.SettingsFragmentTwo"        android:title="@string/prefs_category_two"        android:summary="@string/prefs_summ_category_two" /></preference-headers>


 



代碼清單5-13


然后讓我們再看下3.0以下版本的代碼清單5-14中(res/xml/preference_headers_legacy.xml):




<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">    <Preference         android:title="@string/prefs_category_one"        android:summary="@string/prefs_summ_category_one"  >        <intent             android:targetPackage="com.example.prefs"            android:targetClass="com.example.prefs.SettingsActivity"            android:action="com.example.prefs.PREFS_ONE" />    </Preference>    <Preference         android:title="@string/prefs_category_two"        android:summary="@string/prefs_summ_category_two" >        <intent             android:targetPackage="com.example.prefs"            android:targetClass="com.example.prefs.SettingsActivity"            android:action="com.example.prefs.PREFS_TWO" />    </Preference></PreferenceScreen>


 



代碼清單5-14


因?yàn)閍ndroid3.0中支持<preference-headers>,僅在android3.0或更高版本中系統(tǒng)會在PreferenceActivity中調(diào)用onBuildHeaders()方法。當(dāng)然如果用戶的系統(tǒng)不是3.0(HONEYCOMB)的你就必須調(diào)用preference_headers_legacy.xml,然后調(diào)用addPreferencesFromResource()來載入xml文件。例如代碼清單5-15所示:




@Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    ...     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {        //低于3.0版本載入legacy preferences headers        addPreferencesFromResource(R.xml.preference_headers_legacy);    }} // 高于或等于3.0版本會調(diào)用此方法@Overridepublic void onBuildHeaders(List<Header> target) {   loadHeadersFromResource(R.xml.preference_headers, target);}


 



代碼清單5-15


剩下的3.0以下版本就是通過處理Intent來識別哪個(gè)preference文件要被加載到Activity中來。所以需要檢索intent的action并與在preference XML<intent>下已知action字符串比較,如代碼清單5-16所示:




final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";... @Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);     String action = getIntent().getAction();    if (action != null && action.equals(ACTION_PREFS_ONE)) {        addPreferencesFromResource(R.xml.preferences);    }    ...     else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {        // 載入3.0以下版本的legacy preferences文件        addPreferencesFromResource(R.xml.preference_headers_legacy);    }}


 



代碼清單5-16


注意連續(xù)調(diào)用addPreferencesFromResource()會堆疊所有的preferences到一個(gè)單獨(dú)的列表中,所以確保他只調(diào)用一次,把它寫到else-if的條件分支下。


5.7 讀取Preferences


默認(rèn)的,所有你應(yīng)用中的preferences會保存到一個(gè)文件中,你可以調(diào)用靜態(tài)方法PreferenceManager.getDefaultSharedPreferences()來獲得你保存的preferences。它將返回一個(gè)SharedPreferences對象包含所有你在PreferenceActivity中使用的Preference對象的鍵值對。例如,下面代碼清單5-17教你如何讀取:




SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");


 



代碼清單5-17


5.7.1監(jiān)聽Preference的改變


有些情況下你可能想只要一個(gè)preferences改變你就想得到通知。當(dāng)任意一個(gè)preferences發(fā)生改變時(shí),為了取得一個(gè)回調(diào),我們可以實(shí)現(xiàn)SharedPreference.OnSharedPreferenceChangeListener這個(gè)接口并通過SharedPreferences.registerOnSharedPreferenceChangeListener()來注冊監(jiān)聽。這個(gè)接口只有一個(gè)回調(diào)方法,就是onSharedPreferenceChanged()你很容易就找到。如代碼清單5-18所示:




public class SettingsActivity extends PreferenceActivity                              implements OnSharedPreferenceChangeListener {    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";    ...     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {        if (key.equals(KEY_PREF_SYNC_CONN)) {            Preference connectionPref = findPreference(key);            // 為選中的值設(shè)置用戶描述摘要。            connectionPref.setSummary(sharedPreferences.getString(key, ""));        }    }}


 



代碼清單5-18


這個(gè)例子中,onSharedPreferenceChanged()方法會檢測改變的設(shè)置是否為一個(gè)已知的preference key。如果是就會調(diào)用findPreference()來獲得Preference對象,并且這是改變后的對象你可以做你想做的事情,這里我們設(shè)置了一個(gè)摘要用于當(dāng)用戶選中時(shí)給出提示信息。其實(shí)這是一個(gè)比較好的方法,特別是多個(gè)被選中時(shí),你可以通過現(xiàn)有的API讓用戶知道他們做了些什么并得到反饋。還有請注意記得在Activity聲明周期中的onPause()和 onResume()方法中注冊于注銷你的監(jiān)聽,如代碼清單5-19所示:




@Overrideprotected void onResume() {    super.onResume();    getPreferenceScreen().getSharedPreferences()            .registerOnSharedPreferenceChangeListener(this);} @Overrideprotected void onPause() {    super.onPause();    getPreferenceScreen().getSharedPreferences()            .unregisterOnSharedPreferenceChangeListener(this);}


 



代碼清單5-19


5.8 管理網(wǎng)絡(luò)的使用


從Android4.0開始,系統(tǒng)的設(shè)置應(yīng)用程序允許用戶能看到他們的應(yīng)用程序在前臺和后臺使用了多少網(wǎng)絡(luò)數(shù)據(jù)。用戶對于個(gè)別Apps能關(guān)閉使用后臺數(shù)據(jù)。為了避免用戶關(guān)閉你的程序從后臺訪問數(shù)據(jù)的功能,你應(yīng)該使用數(shù)據(jù)連接有效并允許用戶通過你應(yīng)用程序的設(shè)置來完善你應(yīng)用程序的數(shù)據(jù)使用。例如你可能允許用戶控制你的APP多久同步一次數(shù)據(jù),是否你的app僅在Wifi情況下才更新和下載,漫游情況下如何處理等。這樣的好處是給用戶更精準(zhǔn)的控制你的程序使用多少數(shù)據(jù),有這樣的精準(zhǔn)控制,用戶就不會在系統(tǒng)設(shè)置中直接把你的應(yīng)用訪問數(shù)據(jù)的功能給關(guān)掉。一旦你在PreferenceActivity 中添加了必要的preferences來控制你App的數(shù)據(jù),并養(yǎng)成了這種寫程序的習(xí)慣,那接下來我很樂意給你說明一下,你應(yīng)該在manifest文件中添加一個(gè)intent filter名字為ACTION_MANAGE_NETWORK_USAGE,如代碼清單5-20所示:




<activity android:name="SettingsActivity" ... >    <intent-filter>       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />       <category android:name="android.intent.category.DEFAULT" />    </intent-filter></activity>


 



代碼清單5-20


這個(gè)intent filter表明了這個(gè)activity告訴系統(tǒng)我能控制這個(gè)應(yīng)用程序的數(shù)據(jù)使用。因此,當(dāng)用戶在設(shè)置應(yīng)用中檢查你app使用了多少數(shù)據(jù)時(shí),一個(gè)App設(shè)置按鈕便可用了,你點(diǎn)擊它會啟動PreferenceActivity然后讓用戶在精確控制你的app數(shù)據(jù)使用情況。


5.9 構(gòu)建自定義的Preference


Android框架包含各種各樣的Preference子類允許你構(gòu)建自己的UI。然而你可能發(fā)現(xiàn)一個(gè)設(shè)置沒有好的內(nèi)置方案,如一個(gè)number picker或date picker。在這種情況下你需要創(chuàng)建自定義的preference,你需要繼承Preference類。當(dāng)然擴(kuò)展Preference類后有一些重要的事情要做:


◆當(dāng)用戶選擇設(shè)置的時(shí)候指定用戶接口


◆在適當(dāng)?shù)那闆r下保存setting的值


◆當(dāng)進(jìn)入我們的View時(shí),使用當(dāng)前值或默認(rèn)值初始化Preference


◆當(dāng)被系統(tǒng)請求時(shí),提供默認(rèn)值


◆如果Preference提供它自己的UI(如一個(gè)對話框),保存和恢復(fù)狀態(tài)并處理生命周期的改變 。


5.9.1指定用戶界面


如果你直接擴(kuò)展Preference類,當(dāng)用戶選擇一個(gè)item時(shí),你需要實(shí)現(xiàn)onClick()用來定義action。其實(shí)大部分情況下就是直接繼承的DialogPreference顯示對話框的形式,這樣簡化的程序。如果你繼承了DialogPreference,你必須在類的構(gòu)造函數(shù)中調(diào)用setDialogLayoutResourcs()來指定布局。如代碼清單5-21所示:




public class NumberPickerPreference extends DialogPreference {    public NumberPickerPreference(Context context, AttributeSet attrs) {        super(context, attrs);                setDialogLayoutResource(R.layout.numberpicker_dialog);        setPositiveButtonText(android.R.string.ok);        setNegativeButtonText(android.R.string.cancel);                setDialogIcon(null);    }    ...}


 



代碼清單5-21


5.9.2保存設(shè)置的值


你可以在任意時(shí)刻調(diào)用Preference類的persist*()方法來保存一個(gè)值,如設(shè)置的值為int,那么就使用persistInt()。這個(gè)方法用在對話框關(guān)閉的時(shí)候調(diào)用比較好,它會給用戶一個(gè)提示。當(dāng)點(diǎn)擊positive按鈕時(shí),你就可以保存新的值。如代碼清單5-22所示:




@Overrideprotected void onDialogClosed(boolean positiveResult) {    // 當(dāng)用戶選擇OK時(shí),保存新的值    if (positiveResult) {        persistInt(mNewValue);    }}


 



代碼清單5-22


在上面這個(gè)例子中,mNewValue是一個(gè)類成員變量,并且是int型的。


5.9.3初始化當(dāng)前值


當(dāng)系統(tǒng)添加你的Preference 到屏幕時(shí),它會調(diào)用onSetInitialValue() 來通知你的值是否是已經(jīng)存在的值。如果不存在,這個(gè)調(diào)用會提供一個(gè)默認(rèn)值。onSetInitialValue()方法通過一個(gè)boolean值來表明一個(gè)值是否已經(jīng)被存儲了。如果為true,你應(yīng)該把存儲的值給取出來,你可以使用getPersistedInt()這樣類似的方法取值。如果restorePersistedValue這個(gè)參數(shù)的值為false,那么你就可以使用第二個(gè)默認(rèn)值參數(shù)了,如代碼清單5-23所示:




@Overrideprotected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {    if (restorePersistedValue) {        // 恢復(fù)狀態(tài)        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);    } else {        // 從xml屬性中設(shè)置默認(rèn)狀態(tài)        mCurrentValue = (Integer) defaultValue;        persistInt(mCurrentValue);    }}


 



代碼清單5-23


請注意這里當(dāng)restorePersistedValue為true時(shí)不能使用參數(shù)自帶的defaultValue,因?yàn)樗闹禐閚ull,只有當(dāng)restorePersistedValue為false時(shí)才能使用。


5.9.4提供一個(gè)默認(rèn)值


如果Preference的實(shí)例指定一個(gè)默認(rèn)值(使用android:defaultValue屬性),那么當(dāng)Preference實(shí)例化對象時(shí)為了取得默認(rèn)值,系統(tǒng)會調(diào)用onGetDefaultValue()方法。你必須實(shí)現(xiàn)這個(gè)方法,這樣在系統(tǒng)保存默認(rèn)值到SharedPreferences的時(shí)候才能正確處理。例如代碼清單5-24所示:



@Overrideprotected Object onGetDefaultValue(TypedArray a, int index) {    return a.getInteger(index, DEFAULT_VALUE);}


 


代碼清單5-24


方法參數(shù)提供你需要的一切:數(shù)組屬性和你需要檢索的android:defaultValue的索引位置,原因你必須實(shí)現(xiàn)這個(gè)方法來提取默認(rèn)值的屬性,因?yàn)槟仨氈付ㄒ粋€(gè)本地屬性的默認(rèn)值,以防值是未定義的。


5.9.5保存和恢復(fù)Preference的狀態(tài)


就像一個(gè)在布局中的View,你的Preference子類負(fù)責(zé)保存和恢復(fù)它的狀態(tài),以防止activity和fragment被重新啟動。妥善保存和恢復(fù)你Preference類的狀態(tài),你必須實(shí)現(xiàn)生命周期中的onSaveInstanceState()和onRestoreInstanceState()回調(diào)。Preference的狀態(tài)可以通過Parcelable接口實(shí)現(xiàn)。Android框架提供這樣一個(gè)對象,你可以作為入口點(diǎn)定義你對象的狀態(tài),比如Preference.BaseSavedState類。定義你Preference保存狀態(tài),你應(yīng)該繼承Preference.BaseSavedState類。你需要重寫一些方法來定義CREATOR對象。對于大部分應(yīng)用程序,你可以直接復(fù)制一下實(shí)現(xiàn)并做一些簡單的改變即可,如代碼清單5-25所示:




private static class SavedState extends BaseSavedState {    int value;     public SavedState(Parcelable superState) {        super(superState);    }     public SavedState(Parcel source) {        super(source);        // 獲得當(dāng)前preference的值        value = source.readInt();      }     @Override    public void writeToParcel(Parcel dest, int flags) {        super.writeToParcel(dest, flags);        // 寫入preference的值        dest.writeInt(value);      }     public static final Parcelable.Creator<SavedState> CREATOR =            new Parcelable.Creator<SavedState>() {         public SavedState createFromParcel(Parcel in) {            return new SavedState(in);        }         public SavedState[] newArray(int size) {            return new SavedState[size];        }    };}


 



代碼清單5-25


下面是具體運(yùn)用在onSaveInstanceState()和andonRestoreInstanceState()中的過程,如代碼清單5-26所示:




@Overrideprotected Parcelable onSaveInstanceState() {    final Parcelable superState = super.onSaveInstanceState();    // 檢查Preference是否被保存過    if (isPersistent()) {        //不需要保存實(shí)例狀態(tài),因?yàn)樗浅志没?使用父類狀態(tài)        return superState;    }     // 創(chuàng)建自定義的BaseSavedState實(shí)例    final SavedState myState = new SavedState(superState);    // 使用類成員變量賦值    myState.value = mNewValue;    return myState;} @Overrideprotected void onRestoreInstanceState(Parcelable state) {    //檢查我們在onSaveInstanceState中是否保存過狀態(tài)    if (state == null || !state.getClass().equals(SavedState.class)) {        // 沒有保存狀態(tài),調(diào)用父類的方法        super.onRestoreInstanceState(state);        return;    }     // 強(qiáng)制轉(zhuǎn)換到自定義的BaseSavedState    SavedState myState = (SavedState) state;    super.onRestoreInstanceState(myState.getSuperState());        // 應(yīng)用它的值到UI,以恢復(fù)UI狀態(tài)    mNumberPicker.setValue(myState.value);}


 



代碼清單5-26


 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
PreferenceActivity和PreferenceFragment
Android系統(tǒng)設(shè)置apk
PreferenceActivity用法簡介
android 首選項(xiàng) EditTextPreference
Android之PreferenceActivity
Android的設(shè)置界面及Preference使用
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服