1.Shared Preferences html
是一個簡單,輕量級的,以鍵值對的機制(name/value pair---NVP)存儲一些基礎數據(Boolean,string,float等),最經常使用在保存用戶的APP參數。 java
2.保存APP~UI狀態 android
當APP被移到後臺,Activity和Fragment都包含用來幫助記錄當前UI狀態的生命週期事件回調函數。 緩存
3.Files 安全
文件不是完美的選擇,可是有時候讀寫文件是惟一的選擇。安卓可讓你在外部或者內部媒介上建立文件,也提供支持在公有訪問的文件夾下建立臨時緩存文件和存儲文件。 app
去建立或者修改Shared Prefence,經過調用getSharedPreferences. 框架
SharedPreferences mySharedPreferences = getSharedPreferences(MY_PREFS,Activity.MODE_PRIVATE); 異步
如何去修改呢? ide
答:使用SharedPreferences.Editor類。 函數
SharedPreferences.Editor editor = mySharedPreferences.edit();
根據指定的鍵,使用put方法去更新或者插入值。
// Store new primitive types in the shared preferences object. editor.putBoolean(「isTrue」, true); editor.putFloat(「lastFloat」, 1f); editor.putInt(「wholeNumber」, 2); editor.putLong(「aNumber」, 3l); editor.putString(「textEntryValue」, 「Not Empty」);
完了後,須要提交一下,使用editor.apply()或者editor.commit() 前者是異步的,後者是同步的。
注意:apply方法是在API level 9(Android 2.3)引入的。使用此方法,能夠安全得異步寫入。由於是異步,因此一般這個方法更受歡迎。
若是你使用commit呢,是會阻塞調用的線程,寫入成功會返回true,反之亦然。
直接看代碼:用起來相似於hashMap,第2個參數是默認值,就是若是沒有就返回默認值。
// Retrieve the saved values. boolean isTrue = mySharedPreferences.getBoolean(「isTrue」, false); float lastFloat = mySharedPreferences.getFloat(「lastFloat」, 0f); int wholeNumber = mySharedPreferences.getInt(「wholeNumber」, 1); long aNumber = mySharedPreferences.getLong(「aNumber」, 0); String stringPreference = mySharedPreferences.getString(「textEntryValue」, 「」);
再看:
Map<String, ?> allPreferences = mySharedPreferences.getAll(); //獲取所有
boolean containsLastFloat = mySharedPreferences.contains(「lastFloat」); //是否包含這個鍵
安卓提供一個基於XML驅動的框架,爲你的APP建立系統風格的Preferences Screens。經過使用這個框架你能夠建立Preferences Activities(此activity在原生APP或者第3方APP都保持風格一致)。
Preference框架包含4部分:
1.Preference Screen layout Preference Screen的佈局文件。
2.Preference Activity 和 Preference Fragment 分別繼承與PreferenceActivity和PreferenceFragment, 被用來支持Preference Screen。在Android 3.0以前,Preference Activities直接支持Preference Screen,可是如今, PreferenceScreen<---PreferenceFragment<----Activity。
3.Preference Header Definition 3.0後引入
4.Shared Preference Change Listener 實現了onSharedPreferenceChangeListener的類,來監聽某個Shared Preferences的狀態改變。
這種佈局是作爲xml資源,而不是layout資源,存放在res/xml下,程序中以R.xml.文件名.
首先須要一對<PreferenceScreen>標籤,
<?xml version=」1.0」 encoding=」utf-8」?> <PreferenceScreen xmlns:android=」http://schemas.android.com/apk/res/android」> </PreferenceScreen>
PreferenceCategory 用來分類,以標題欄做爲分隔符,像個容器:
<PreferenceCategory
android:title=」My Preference Category」/>
Preference的控制視圖至少包含:
1.android:key 這個與Shared Preference的key有關。
2.android:title 爲這個Preference顯示錶明性的標題。
3.android:summary 以略微小的字體,略長的字數,概述當前的preference。
4.android:defaultValue 默認值,若是未設置。
下面舉一個簡單的example,包含PreferenceCategory和CheckBox Preference
<?xml version=」1.0」 encoding=」utf-8」?> <PreferenceScreen xmlns:android=」http://schemas.android.com/apk/res/android」> <PreferenceCategory android:title=」My Preference Category」> <CheckBoxPreference android:key=」PREF_CHECK_BOX」 android:title=」Check Box Preference」 android:summary=」Check Box Preference Description」 android:defaultValue=」true」 /> </PreferenceCategory> </PreferenceScreen>
PreferenceCategory 更像一個分門別類的容器。
1.CheckBoxPreference
2.EditTextPreference
3.ListPreference
4.MultiSelectListPreference Android 3.0(API level 11) 引入,與check box list相等效果。
5.RingtonePreference 當你想構建一個爲設置Notification的視圖,會頗有用。
具體不解釋,試試纔是真諦。
你還能夠自定義自個兒的preference控制視圖,經過繼承Preference類。更多細節,參考
http://developer.android.com/reference/android/preference/Preference.html
除了剛纔那些,preference層級視圖中你還能夠加入其它APP的Preference Screen.
先看片斷:
<?xml version=」1.0」 encoding=」utf-8」?> <PreferenceScreen xmlns:android=」http://schemas.android.com/apk/res/android」 android:title=」Intent preference」 android:summary=」System preference imported using an intent」> <intent android:action=」android.settings.DISPLAY_SETTINGS 「/> </PreferenceScreen>
系統視此intent爲請求,會調用startActivity()。
android.provider.Settings 類包含一些android.settings.*常量,這些常量能夠被用來調用系統設置界面。
以往是:先定義個xml Preference Screen佈局文件,而後再建立個類繼承PreferenceActivity,在onCreate中:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preference_layout); }
注意這是一種xml資源。
activity都是要註冊的。
3.0後步驟是:先建立個繼承於PreferenceFragment的類,在其onCreate中:
@Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); this.addPreferencesFromResource(R.xml.preference_layout); }
而後寫個xml preference-headers文件:
<?xml version="1.0" encoding="utf-8"?> <preference-headers xmlns:android="http://schemas.android.com/apk/res/android" > <header android:fragment="com.example.test.PreFragment" android:icon="@drawable/ic_launcher" android:title="My Preferences" android:summary="Description of these preferences"/> </preference-headers>
最後建立個繼承於PreferenceActivity的類,重寫方法onBuildHeaders:
@Override public void onBuildHeaders(List<Header> target) { super.onBuildHeaders(target); this.loadHeadersFromResource(R.xml.pref_header, target); }
preference-header也是屬於xml資源。
3.0前,關係是 PreferenceScreen xml---PreferenceActivity
3.0後,關係是 PreferenceScreen xml-PreferenceFragment—preference-header—PreferenceActivity
<header android:icon=」@drawable/ic_settings_display」 android:title=」Intent」 android:summary=」Launches an Intent.」> <intent android:action=」android.settings.DISPLAY_SETTINGS 「/> </header>
這個header就沒有指定PreferenceFragment了.
爲你的程序預先建立2種版本:
Class c = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? MyPreferenceActivity.class : MyFragmentPreferenceActivity.class; Intent i = new Intent(this, c); startActivityForResult(i, SHOW_PREFERENCES);
Build.VERSION.SDK_INT 意思是你當前項目編譯的版本,若是小於Build.VERSION_CODES.HONEYCOMB 3.0,那麼我就選擇MyPreferenceActivity.class,不然MyFragmentPreferenceActivity。
上述是一種兼容解決方案。
答:
Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); // TODO Retrieve values using get<type>
使用PreferenceManager.getDefaultSharedPreferences得到的SharedPreferences,是能夠被APP全部組件共享的。
既然是個監聽者,那就說說何時會觸發。
當Shared Preference值被增長,移除或者修改的時候觸發。
一般這會很是有用,給Activities和Services使用Shared Preferences框架去設置APP preferences,若是合適的話,以此來更新UI和APP的行爲。
答:就是前面提到的PreferenceManager.getDefaultSharedPreferences方式得到的,具備全局意義的,能夠被app全部組件共享的。
下面看個實現的例子:
public class MyActivity extends Activity implements OnSharedPreferenceChangeListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Register this OnSharedPreferenceChangeListener SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); } public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { // TODO Check the shared preference and key parameters // and change UI or behavior as appropriate. } }
1.以PreferenceManager.getDefaultSharedPreferences,這種保存的能夠被App全部組件獲取
2.Activtiy.getSharedPreferences 這個方法,能夠指定一個名字,只要名字正確,也是能夠全局被獲取。
3.Activity.getPreferences()這個方法所保存的是針對於當前的activity,不是全局。
// Create or retrieve the activity preference object. SharedPreferences activityPreferences = getPreferences(Activity.MODE_PRIVATE); // Retrieve an editor to modify the shared preferences. SharedPreferences.Editor editor = activityPreferences.edit(); // Retrieve the View TextView myTextView = (TextView)findViewById(R.id.myTextView); // Store new primitive types in the shared preferences object. editor.putString(「currentTextValue」, myTextView.getText().toString()); // Commit changes. editor.apply();
Activity提供onSaveInstanceState回調函數去保存與UI狀態相關的數據,主要情形呢:activity在後臺由於資源緊張被殺死,待資源恢復後,或者是硬件配置改變後致使的重啓,須要恢復以前的UI狀態。
private static final String TEXTVIEW_STATE_KEY = 「TEXTVIEW_STATE_KEY」; @Override public void onSaveInstanceState(Bundle saveInstanceState) { // Retrieve the View TextView myTextView = (TextView)findViewById(R.id.myTextView); // Save its state saveInstanceState.putString(TEXTVIEW_STATE_KEY, myTextView.getText().toString()); super.onSaveInstanceState(saveInstanceState); }
當Activity重啓的時候,saveInstanceState變量會傳給onCreate和onRestoreInstanceState.
注意:正常的結束是不會產生saveInstanceState變量的。所謂正常,就是在前臺用戶選擇了退出。(如按返回鍵)致使了finish,觸發onDestory。
恢復的小DEMO:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView myTextView = (TextView)findViewById(R.id.myTextView); String text = 「」; if (savedInstanceState != null && savedInstanceState.containsKey(TEXTVIEW_STATE_KEY)) text = savedInstanceState.getString(TEXTVIEW_STATE_KEY); myTextView.setText(text); }
大多數APP的UI,都會內嵌在Fragments中。相應的,Fragments也包含了一個onSaveInstanceState回調函數,很像activity。
它所產生的Bundle對象,會傳遞給onCreate,onCreateView,onActivityCreated。
若是一個Activity由於硬件配置改變,實例被殺死而後重啓,好比屏幕翻轉等,你可讓你的fragment實例不作任何改變,經過在Fragment的onCreate中調用setRetainInstance便可,這樣的話相關的activity重啓,也無論它的事兒了,fragment的實例不會被殺死,就不會被從新建立。
注意:onCreate和onDestory那時候不會被觸發了,即使如此,onAttach,onCreateView,onActivityCreated,onStart,onResume和它們的一致的事件函數仍是會被調用。
(在onCreate方法中保存初始化,這樣就最大化的保存狀態了,效率比起之前沒有fragment仍是有好處的)
public class MyFragment extends Fragment { private static String USER_SELECTION = 「USER_SELECTION」; private int userSelection = 0; private TextView tv; @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 v = inflater.inflate(R.layout.mainfragment, container, false); tv = (TextView)v.findViewById(R.id.text); setSelection(userSelection); Button b1 = (Button)v.findViewById(R.id.button1); Button b2 = (Button)v.findViewById(R.id.button2); Button b3 = (Button)v.findViewById(R.id.button3); b1.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { setSelection(1); } }); b2.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { setSelection(2); } }); b3.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { setSelection(3); } }); return v; } private void setSelection(int selection) { userSelection = selection; tv.setText(「Selected: 「 + selection); } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(USER_SELECTION, userSelection); super.onSaveInstanceState(outState); } }