SharedPreference 當存儲 UI 狀態、用戶首選項、應用程序設置時,咱們須要一種輕量級機制以存儲一個已知的值集。SharedPreference 可以保存一組原始數據的名、值對保存爲命名的首選項。java
已保存的應用程序 UI 狀態 當應用程序移動到後臺時,Activity 和 Fragment 會包含專用的事件處理程序以記錄當前的 UI 狀態android
文件 Android 使咱們可以在設備的內部或外部媒體上建立並加載文件,它做爲臨時緩存提供了支持,並將文件存在公用可訪問的文件夾中。緩存
使用 SharedPreference 類能夠建立名稱/值對,他們能夠在會話之間持久化,並在同一個應用程序沙箱中運行的組件之間共享。安全
SharedPreference 存儲在應用程序的沙箱中,因此能夠在應用程序組件之間共享,可是對其餘應用程序來講不可用。app
在Android系統中, 其配置文件的數據文件 以XML文件的形式保存在 /data/data/PACKAGE_NAME/shared_prefs
目錄下框架
建立 SharedPreference:SharedPreferences preferences = getSharedPreferences("Jack", Activity.MODE_PRIVATE);
異步
Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
修改 SharedPreference:SharedPreferences.Editor editor = preferences.edit();
ide
插入或更新 SharedPreference:函數
editor.putString("TextName", "Jack"); editor.putInt("last", 1);
保存編輯的動做:佈局
// 異步保存 editor.apply(); // 同步保存 editor.commit();
使用類型安全的 get<Type>
方法來提取已保存的值,每一個 getter 都接受一個鍵和一個默認值。
也能夠經過 getAll
返回全部的 SharedPreference 鍵值的一個映射。經過調用 contains
方法能夠查詢特定的鍵是否存在。
Android 中提供了一個 XML 驅動的框架,用來爲應用程序建立系統樣式的 Preference Screen。經過使用該框架,可以確保應用程序中的 Preference Activity 與本地和其餘第三方應用程序中所使用的一致。
Preference Activity 框架由下面 5 部分組成:
一個 onSharedPreferenceChangeListener
類的實現,用於監聽 SharedPerference 的變化。每當添加、刪除或修改一個特定的 SharedPreference 時來回調該函數。
一個佈局控制文件,它指定了要顯示的文本和相關控件、所容許的值和爲每一個空間使用的 SharedPreference 鍵。定義XML文件在 res/xml
目錄下。
Preference Screen 文件包含如下幾個元素組成:
Preference Screen 文件包含如下幾種控件類型:
此外也能夠經過擴展 Preference 類 或上述控件來建立屬於本身的首選項控件。
是從 API Level 11 以後才添加進來的,用來包含 Preference Screen 資源定義。須要繼承此類來建立一個新的 Preference Fragment。
爲 Preference Fragment 填充首選項,須要重寫 onCreate 方法,並調用 addPreferencesFromResource
方法
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.userpreferences); }
Preference Header 是 XML 資源,存在 res/xml
文件夾下,每一個資源文件名稱就是它的 ID,每一個 Preference Header 必須關聯一個 Preference Fragment,必須指定 Preference Header 的標題。還能夠選擇一個 圖標。
對於不一樣的屏幕尺寸版本,用於顯示頭及其相關 Fragment 的佈局也可能不一樣。
Preference Activity 類用於包含由 Preference Header 資源定義的 Preference Fragment 層次結構。在 Android 3.0 以前,Preference Activity 用於直接包含 Preference Screen。若是在 Android 3.0 以前運行,則仍是須要直接使用 Preference Activity。
當須要使用 Preference Fragment 和 Preference Header 時,須要重寫 onBuildHeaders
處理程序,在其中調用 loadHeadersFromResources
並指定一個 Preference Header 資源文件:
public void onBuildHeaders(List<Header> target) { loadHeadersFromResource(R.xml.preference_headers, target); }
當裝載 Preference Fragment 和 Preference Header 時,重寫 onCraete
處理程序,在其中調用 addPreferencesFromResource
方法:
public void onCreate(Bundle savedInstanceState) { addPreferencesFromResource(R.xml.preference_headers); }
最後像全部 Activity 程序同樣,在 manifest 文件中添加 activity
經過 Intent 導入系統的首選項,把系統首選項顯示內容添加到 preference screen 中
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <intent android:action="android.settings.DISPLAY_SETTINGS" /> </PreferenceScreen>
Preference Fragment 和 Preference Header 是在 Android API Level 11 中才被引入的,低於 API 11 版本的將不會被支持,所以要作一些處理,讓低於 11 版本的 API 繼續使用 Preference Activity。
Class c = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? UserPreferencesActivity.class : FragmentPreferences.class; Intent i = new Intent(this, c);
若是你想要保存並不須要與其餘組件共享的 Activity 信息(類實例變量),那麼能夠調用 Activity.getPreferences(),而不須要指定一個 SharedPreference 名稱,這會返回一個 SharedPreference,其名稱就是調用 Activity 的名稱。
// 建立或檢索 Activity 首選項對象 SharedPreferences sharedPreferences = this.getPreferences(Activity.MODE_PRIVATE);
Activity 提供了 onSaveInstanceState 處理程序來保存與會話之間的 UI 狀態關聯數據,若是 Activity 是由用戶關閉的(或按下 onBack 按鍵)或調用 finish 關閉的。那麼下一次建立 Activity 時,實力狀態 Bundle 是不會傳遞給 onCreate 和 onRestoreInstanceState。
經過重寫一個 Activity 的 onSaveInstanceState 事件處理程序,可使用它的 Bundle 參數來保存 UI 實例的值。每當 Activity 完成了生命週期,可是尚未被顯式的結束(調用 finish)時,該處理程序將會觸發。
protected void onSaveInstanceState(Bundle saveInstanceState) { // 檢索視圖 TextView textView = (TextView) findViewById(R.id.title); // 保存狀態 saveInstanceState.putString(TEXTVIEW_STATE_KEY, textView.getText().toString()); super.onSaveInstanceState(saveInstanceState); }
若是應用程序被強制重啓,那麼已保存的 Bundle 參數就會被傳入 onRestoreInstanceSave 和 onCreate 方法中。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.title); String text = ""; if (savedInstanceState != null && savedInstanceState.containsKey(TEXTVIEW_STATE_KEY)) text = savedInstanceState.getString(TEXTVIEW_STATE_KEY); textView.setText(text); }
大多數應用程序的實例都封裝在 Fragment 內,Fragment 也包含一個 onSaveInstanceState 處理程序,其工做方式與 Activity 中的對應處理程序十分類似。
持久化到 Bundle 中的實例狀態做爲參數傳遞給 Fragment 的 onCreate、onCreateView 和 onActivityCreated 處理程序。
在 Activity 被銷燬而後被從新啓動,以及處理硬件配置改變的狀況下,能夠請求保存 Fragment 的狀態。設置 Fragment 的 onCreate 處理程序內的 setRetainInstance 方法爲 true
以後,當 Activity 被從新建立時,Fragment 的實例不該該被終止和從新啓動。
所以,當設備配置改變,而且 Activity 被銷燬和從新建立時,Fragment 的 onDestroy 和 onCreate 不會被調用。若是將大部分對象建立代碼移入 onCreate,同時使用 onCreateView 和已保存的實例值中存儲的值來更新 UI,這樣能夠顯著的提交效率。
public static class PlaceholderFragment extends Fragment { private static final String USER_SELECTION = ""; private int userSelection = 0; private TextView tv; public PlaceholderFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); if (savedInstanceState != null) { userSelection = savedInstanceState.getInt(USER_SELECTION); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); tv = (TextView) rootView.findViewById(R.id.text); setSelection(userSelection); Button button1 = (Button) rootView.findViewById(R.id.button1); Button button2 = (Button) rootView.findViewById(R.id.button2); Button button3 = (Button) rootView.findViewById(R.id.button3); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setSelection(1); } }); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setSelection(2); } }); button3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setSelection(3); } }); return rootView; } private void setSelection(int selection) { userSelection = selection; tv.setText("Selected: " + selection); } @Override public void onSaveInstanceState(Bundle saveInstanceState) { saveInstanceState.putInt(USER_SELECTION, userSelection); super.onSaveInstanceState(saveInstanceState); } }