Activity的生命週期及Intent(ActivityLifeCycle)
1.Android生命週期
Android是使用任務棧(Task)來管理活動的,一個任務就是一組存放在棧裡的活動的集合,這個棧也被稱作返回棧(Back Stack)。棧是一種後進先出的資料結構*(後來者居上)。在預設情況下,每當我們啟動了一個新的活動,它會在返回棧中入棧,並處於棧頂的位置。而每當我們按下Back鍵或呼叫finish()方法去銷燬一個活動時,處於棧頂的活動就會出棧,這時前一個入棧的活動就會重新處於棧頂的位置。系統總是會顯示處於棧頂的活動給使用者。活動生命週期的四種狀態:
①執行狀態,當一個活動位於返回棧的棧頂時,這時活動就處於執行狀態。系統最不願意回收的就是處於執行狀態的活動,因為這會帶來非常差的使用者體驗。
②暫停狀態,當一個活動不再處於棧頂位置,但仍然可見時,這時活動就進入了暫停狀態,比如有一些活動以對話方塊的形式出現,只會佔用螢幕中間的部分位置,處於其下仍然可見的活動就是暫停狀態,系統也不願去回收這種狀態的活動(活動對於使用者仍然是可見的)。
③停止狀態:當一個活動不再處於棧頂位置,並且完全不可見的時候就進入了停止狀態,當有其他地方需要記憶體時,處於停止狀態的活動有可能會被系統回收。
④銷燬狀態:當一個活動從返回棧中移除後就變成銷燬狀態。系統會最傾向於回收這種狀態的活動,從而保證手機記憶體充足。
二、活動生命週期具體分析:Activity類中定義了7個回撥方法,覆蓋了活動生命週期的每隔環節。
①onCreate(),它會在活動第一次被建立的時候呼叫。開發者要在這個方法中完成活動的初始化操作,比如說載入佈局、繫結時間等。
②onStart(),這個方法在活動由不可見變為可見的時候呼叫。
③onResume(),這個方法在活動準備好和使用者進行互動的時候呼叫。此時的活動一定位於返回棧的棧頂,並且處於執行狀態。
④onPause(),這個方法在系統準備去啟動或者恢復另一個活動的時候呼叫。我們通常會在這個方法中將一些消耗CPU的資源釋放掉,以及儲存一些關鍵資料,但這個方法的執行速度一定要快,不然會影響到新的棧頂活動的使用。
⑤onStop(),這個方法在活動完全不可見的手呼叫。它和onPause方法的主要區別在於,如果啟動的新活動是一個對話方塊式的活動,那麼onPause()方法會的得到執行,而onStop()方法並不會執行。
⑥onDestroy(),這個方法在活動被銷燬之前呼叫,之後活動的狀態將變成銷燬狀態。
⑦onRestart(),這個方法在活動活動由停止狀態變為執行狀態時呼叫。
以上7個方法除了onRestart()方法之外,都是兩兩對應的,從而又將活動分為三個生存期。
①完整生存期。活動在onCreate方法和OnDestroy方法之間所經歷的,就是完整生存週期。一般情況下,一個活動會在onCreate方法中完成各種初始化操作,而在onDeatroy方法中完成釋放記憶體的操作。
②可見生存期。活動在onStart方法和onStop方法之間所經歷的,就是可見生存期。在可見生存期內,活動對於使用者總是可見的,即便有可能無法和使用者進行互動。我們可以通過這兩個方法,合理地管理那些對使用者的可見的資源。
③前臺生存期。活動在onResume方法和onPause方法之間所經歷的就是前臺生存期。在前臺生存期內,活動總是處於執行狀態,此時的活動是可以和使用者進行互動的,我們平時看到和接觸最多的也就是處於這個狀態下的活動。
小結:到這裡我們來個小結,當Activity啟動時,依次會呼叫onCreate(),onStart(),onResume(),而當Activity退居後臺時(不可見,點選Home或者被新的Activity完全覆蓋),onPause()和onStop()會依次被呼叫。當Activity重新回到前臺(從桌面回到原Activity或者被覆蓋後又回到原Activity)時,onRestart(),onStart(),onResume()會依次被呼叫。當Activity退出銷燬時(點選back鍵),onPause(),onStop(),onDestroy()會依次被呼叫,到此Activity的整個生命週期方法回撥完成。
2.Intent啟動Activity
要建立並顯示一個Activity,可以呼叫startActivity,並傳遞給它一個Intent,如下面的程式碼所示:
startActivity(Intent myIntent);
可以構造Intent來顯示地指定要開啟的Activity類,或者包含一個目標Activity必須執行的動作。在後一種情況中,執行時將會使用一個稱為“Intent解析(Intent resolution)”的過程來動態選擇Activity。
3. 多個Activity之間共享資料
Activity之間共享資料有五種方式:
1.基於訊息的通訊機制 Intent ---boudle ,extra
資料型別有限,比如遇到不可序列化的資料Bitmap,InputStream, 或者LinkList連結串列等等資料型別就不太好用。
2. 利用static靜態資料,public static成員變數,也是可以是一個public類;
3.基於外部儲存的傳輸, File/Preference/ Sqlite ,如果要針對第三方應用需要Content Provider
4.基於IPC的通訊機制context 與Service之間的傳輸,如Activity與Service之間的通訊,定義AIDL介面檔案。
5. 基於Application Context
本程式是使用一個public類實現資料共
定義一個public類Status用來儲存活動狀態和顯示狀態在textview中,該public類定義了Map<String,String>型別的變數mMethodList儲存Activity Status , List<String>型別的變數mStatusMap儲存日誌資訊。
建構函式:
private Status() {
mStatusMap = new LinkedHashMap<String, String>();
mMethodList = new ArrayList<String>();
}
用一個getInstance()方法返回該類的一個物件(該物件封裝了上述兩個變數):
public static Status getInstance() {
return ourInstance;
}
clear()函式用清除mMethodLis和mStatusMap儲存的活動狀態:
public void clear() {//清除日誌表和狀態表
mMethodList.clear();
mStatusMap.clear();
}
setStatus()函式用來將當前活動的資訊存進mMetodList和mStatusMap:
public void setStatus(String activityName, String status) {
mMethodList.add(activityName + "." + status + "()");
if (mStatusMap.containsKey(activityName)) mStatusMap.remove(activityName);
mStatusMap.put(activityName, status);
}
getStatus()函式用來獲取活動狀態,並轉化為輸出格式:
public String getStatus(String activityName) {
String status = mStatusMap.get(activityName);
status = status.substring(2, status.length());//把前面的on去掉
// String manipulation to ensure the status value is spelled correctly.
if (status.endsWith("e")) {
status = status.substring(0, status.length() - 1);//以e結尾直接加d
}
if (status.endsWith("p")) {
status = status + "p";//以p結尾雙寫p加ed
}
status = status + STATUS_SUFFIX;
return status;
}
由於在當前Activity執行onResume()後,onStop()或onDestroy()才執行而且執行的時間很短,如果在執行onResume()的時候直接顯示到TextView會導致onStop或onDestroy()顯示不了,所以在顯示函式printStatus()中設定一個時間延遲,由圖可知時延大概在1.4s左右。該實驗將時延設定為2s。
public static void printStatus(final TextView viewMethods, final TextView viewStatus) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
StringBuilder sbMethods = new StringBuilder();
List<String> listMethods = mStatus.getMethodList();
for (String method : listMethods) {
sbMethods.insert(0, method + "\r\n");
}
if(viewMethods != null) {
viewMethods.setText(sbMethods.toString());
}
StringBuilder sbStatus = new StringBuilder();
for (String key : mStatus.keySet()) {
sbStatus.insert(0,key + ": " + mStatus.getStatus(key) + "\n");
}
if(viewStatus != null) {
viewStatus.setText(sbStatus.toString());
}
}
}, 2000);
}
然後在AActivity、BActivity、CActivity中定義Status物件,然後分別在onCreate(),onStart(),onResume(),onPause(),onDestroy()中呼叫相應函式
3.執行結果截圖
啟動程式初始化介面
緊接著點選START B按鈕後出現的介面
再點選START C按鈕後出現介面
然後點選FINISH C按鈕出現的介面
最後點選DIALOG出現的介面