1.生命周期

第一次啟動(dòng):
onCreate->onStart->onResume
跳轉(zhuǎn)其他頁面:
onPause->onStop
回到頁面:
onRestart->onStart->onResume
結(jié)束當(dāng)前頁面:
onPause->onStop->onDestroy
異常情況下的生命周期分析
onSaveInstanceState 與 onRestoreInstanceState(TextView 等都有這個(gè)方法)
對于 onSaveInstanceState 的調(diào)用說明:
Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
從這句話可以知道,當(dāng)某個(gè)activity變得“容易”被系統(tǒng)銷毀時(shí),該activity的onSaveInstanceState就會(huì)被執(zhí)行(按 home 旋轉(zhuǎn)屏幕等等),除非該activity是被用戶主動(dòng)銷毀的,例如當(dāng)用戶按BACK鍵的時(shí)候。
對于onRestoreInstanceState什么時(shí)候被調(diào)用
onRestoreInstanceState()被調(diào)用的前提是,activity A“確實(shí)”被系統(tǒng)銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會(huì)被調(diào)用,例如,當(dāng)正在顯示activity A的時(shí)候,用戶按下HOME鍵回到主界面,然后用戶緊接著又返回到activity A,這種情況下activity A一般不會(huì)因?yàn)閮?nèi)存的原因被系統(tǒng)銷毀,故activity A的onRestoreInstanceState方法不會(huì)被執(zhí)行 此也說明上二者,大多數(shù)情況下不成對被使用。
- 我們可以通過 onRestoreInstanceState 和 onCreate 方法來判斷Activity是否被重建了,
- 可以通過android:configChanges="orientation|screenSize"...來阻止Activity重新創(chuàng)建。
問題1:
當(dāng)前頁面是 Activity A ,如果用戶打開一個(gè)新的 Activity B, 那么 B 的 onResume 和 A 的 onPause 那個(gè)先執(zhí)行?
A->onPause
B->onCreate
B->onStart
B->onResume
A->onSaveInstanceState
A->onStop
2.任務(wù)棧
Task是為了完成某個(gè)工作的一組相關(guān)聯(lián)的Activity的集合
為了方便大家更直觀感受一下,可以使用adb命令查看一下當(dāng)前運(yùn)行的Task:
adb shell dumpsys activity activities
注意其中的幾個(gè)關(guān)鍵字
Stack
TaskRecord
ActivityRecord
用圖形來表示他們之間的關(guān)系

"Hist"代表Task中的ActivityRecord,可以理解成對應(yīng)某個(gè)實(shí)際的Activity。
"Stack #0"表示mHomeStack(ActivityStack類),保存了Launcher相關(guān)的Activity的Task。
"Stack #1"表示mFocusStack(ActivityStack類),用于保存Launcher除外的其他應(yīng)用的Activity組成的Task。
這兩個(gè)Stack由ActivityStackSupervisor負(fù)責(zé)組織管理,在Android 4.4之前的版本是沒有ActivityStackSupervisor這個(gè)類的,也沒有"Stack #"的劃分,AMS直接管理Task的列表。
TaskRecord{4226f148 #60 A=com.ryg.chapter_1 U=0 sz=5}
Run #5: ActivityRecord{41a7e988 u0 com.ryg.chapter_1/.MainActivity t60}
Run #4: ActivityRecord{41a68f40 u0 com.ryg.chapter_1/.MainActivity t60}
Run #3: ActivityRecord{418d32f8 u0 com.ryg.chapter_1/.MainActivity t60}
Run #2: ActivityRecord{4212a450 u0 com.ryg.chapter_1/.MainActivity t60}
Run #1: ActivityRecord{4226ee78 u0 com.ryg.chapter_1/.MainActivity t60}
其中 com.ryg.chapter_1 代表 taskAffinity 值,我們也可以為一個(gè)Activity指定任務(wù)棧,如下:
TaskAffinity 標(biāo)識(shí)了一個(gè) Activity 所需要的任務(wù)棧。默認(rèn)情況下,所有 Activity 所需的任務(wù)棧的名字為當(dāng)前應(yīng)用的包名。
<activity
android:name="com.ryg.chapter_1.MainActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleTask"
android:taskAffinity = "com.jack.org1"></activity>
3.啟動(dòng)模式
- standard:
標(biāo)準(zhǔn)啟動(dòng),Activity每次都會(huì) onCreate - singleTop:
如果置于棧頂 onNewIntent(),如果棧中不存在這個(gè)Activity,onCreate會(huì)調(diào)用。反之則 onNewIntent(); - singleTask:
檢測整個(gè) Activity 棧是否有當(dāng)前需要啟動(dòng)的 Activity,自帶 clear 屬性。特殊情況:其他程序以 singleTask 啟動(dòng)創(chuàng)建一個(gè)新的任務(wù)棧。 如果棧中不存在這個(gè)Activity,onCreate會(huì)調(diào)用。反之則 onNewIntent(); - singleInstance:
單實(shí)例模式,除了擁有singleTask的屬性外,還加強(qiáng)了一點(diǎn),就是這種模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧中。
指定啟動(dòng)模式
- <manifest> 中指定。
- Intent 中為 Activity 設(shè)置標(biāo)記位,優(yōu)先級(jí)高些。
Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Flags 常見的標(biāo)記位
1.FLAG_ACTIVITY_NEW_TASK
當(dāng)Intent對象包含F(xiàn)LAG_ACTIVITY_NEW_TASK標(biāo)記時(shí),系統(tǒng)在查代時(shí)(和設(shè)置了singleTask啟動(dòng)模式一樣都是)按Activity的taskAffinity屬性進(jìn)行匹配,如果找到一個(gè)Task的taskAffinity與之相同,就將目標(biāo)Activity壓入此Task棧中,如果找不到則創(chuàng)建一個(gè)新的Task。
2.FLAG_ACTIVITY_SINGLE_TOP
3.FLAG_ACTIVITY_CLEAR_TOP
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
不希望用戶通過歷史列表回到我們的 Activity 的時(shí)候,這個(gè)標(biāo)記位比較有用。
4.startActivityForResult
注意點(diǎn):要保證 要啟動(dòng)的 activity 的啟動(dòng)模式是 standard, A 啟動(dòng) B.
一般這樣封裝比較好,如下:
- 在 B 中,設(shè)置一個(gè)方法,供 A 去啟動(dòng) B
public static void startChoosePayActivity(Activity activity, int guaranteeFee, int requestCose) {
Intent intent = new Intent(activity, ChoosePayActivity.class);
intent.putExtra("guaranteeFee", guaranteeFee);
if (requestCose == -1) {
activity.startActivity(intent);
} else {
activity.startActivityForResult(intent, requestCose);
}
}
- 在 B 中傳遞數(shù)據(jù)給 A。
setResult(RESULT_OK, getIntent().putExtra("paytype", result));
finish();
- 在 A 的 onActivityResult 取出值
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case IntentContent.PAYTYPE_SELECT_REQUEST:
int nPaytype = data.getIntExtra("paytype", -1);
E_PAY_TYPE e_pay_type = E_PAY_TYPE.valueOf(nPaytype);
switch (e_pay_type) {
case PAY_ALIPAY:
LogUtils.i(TAG, "支付寶支付");
break;
case PAY_WECHAT:
LogUtils.i(TAG, "微信支付");
break;
case PAY_WALLET:
LogUtils.i(TAG, "錢包支付");
}
break;
}
}
參考資料
相關(guān)鏈接
- 請戳我的博客,如何判斷Activity是否在運(yùn)行
- 請戳我的博客,從源碼分析Activity的啟動(dòng)過程