前言
這是之前欠下的Activity 啟動(dòng)到銷毀的系列文章的總結(jié)即碗。Activity是四大組件中最為復(fù)雜的一環(huán)酵紫,就算是我也沒辦法說我全面的理解了籽腕,因此還是有必要把如下三篇文章,做一次小的總結(jié)惠啄。
- Android 重學(xué)系列 Activity的啟動(dòng)流程(一)
- Android 重學(xué)系列 Activity的啟動(dòng)流程(二)
- Android 重學(xué)系列 Activity的啟動(dòng)流程(三)
這三篇分別論述了Activity在啟動(dòng)中,做的三個(gè)大事情:
- Activity 啟動(dòng)準(zhǔn)備任内, 準(zhǔn)備好ActivityRecord對(duì)象
- Activity 棧的轉(zhuǎn)移與變化
- AMS 如何通信到Activity中執(zhí)行Activity對(duì)應(yīng)的生命周期
如果遇到什么問題歡迎來到本文討論:http://www.reibang.com/p/5da5f2bc8657
正文
我們先上時(shí)序圖:
注意:紅色線代表跨越Binder一次進(jìn)程撵渡。
Activity 啟動(dòng)準(zhǔn)備
在Activity的前期準(zhǔn)備中,做了如下事情:
1.通過
ActivityStackSupervisor
調(diào)用resolveIntentInternal
從PMS中通過Intent篩選出符合目標(biāo)的Activity死嗦,如果符合多個(gè)則切換成另一個(gè)彈窗Activity的啟動(dòng)趋距,這個(gè)Activity包含了當(dāng)前多個(gè)符合Intent目標(biāo)的Activity信息 也就是ActivityInfo
。2.獲取重量級(jí)進(jìn)程,這種進(jìn)程只允許在一個(gè)Android系統(tǒng)內(nèi)只有一個(gè)越走,一旦需要開啟另一個(gè)重量級(jí)進(jìn)程的Activity棚品,就會(huì)彈出一個(gè)彈框的Activity替換代替當(dāng)前的Activity,不過在其中就有了選擇哪一個(gè)進(jìn)程Activity的選項(xiàng)
-
3.Android 9.0比起低版本來說多做不少事情,在
startActivityMayWait
方法中廊敌,會(huì)進(jìn)一步調(diào)用startActivity
真正執(zhí)行啟動(dòng)方法铜跑。根據(jù)執(zhí)行方法返回的狀態(tài)代碼執(zhí)行如下幾種狀態(tài):START_SUCCESS 代表Activity啟動(dòng)成功。往往這種情況下骡澈,很少會(huì)遇到锅纺。一般是進(jìn)程在啟動(dòng)的時(shí)候,被阻塞起來肋殴。直到進(jìn)程啟動(dòng)后囤锉,執(zhí)行了加入棧的處理設(shè)置了狀態(tài)碼為
START_TASK_TO_FRONT
后,解開阻塞护锤。進(jìn)入到START_TASK_TO_FRONT
中.START_DELIVERED_TO_TOP 代表存在的Activity重新回到頂部
START_TASK_TO_FRONT 并沒真正的啟動(dòng)Activity官地,但是Activity對(duì)應(yīng)的棧跑到用戶交互前臺(tái)。而這個(gè)過程中烙懦,又會(huì)阻塞整個(gè)AMS驱入,直到這個(gè)Activity可視化為止。
能看到AMS比起之前來說氯析,約束了整個(gè)Binder通信的吞吐量亏较。從創(chuàng)建到加入Activity棧凡人,再到可視化都變成了一環(huán)扣著一環(huán)的了烛缔。這么做確實(shí)可以減少那些不可見的(不怎么緊急的)Activity啟動(dòng)膘格,占用過多系統(tǒng)資源么鹤。
- 4.從進(jìn)程LRU緩存中邢隧,查找這些進(jìn)程中是否有對(duì)應(yīng)的ActivityRecord是否已經(jīng)存在在某一個(gè)棧旋廷。從
ActivityDisplay
中的ActivityStack
尋找ActivityRecord
5.處理Intent的Flag:
FORWARD_RESULT
.這個(gè)標(biāo)志位就是透?jìng)鱮equestCode時(shí)候的行為膛虫。一般是中間有一個(gè)臨時(shí)的Activity鹃祖,此時(shí)必定可以找到啟動(dòng)這個(gè)臨時(shí)Activity的Activity對(duì)應(yīng)的ActivityRecord
,并且設(shè)置ActivityRecord
為sourceRecord
,并獲取sourceRecord
中的requestCode
和resultWho
作為參數(shù)進(jìn)行覆蓋。并要把獲取當(dāng)前臨時(shí)Activity的棧作為新的Activity啟動(dòng)對(duì)應(yīng)的棧扁达。6.判斷當(dāng)前的啟動(dòng)權(quán)限正卧,判斷條件有三:是被判斷為應(yīng)用有害;被禁止啟動(dòng)的進(jìn)程;被設(shè)置為靜音模式跪解,只要不通過都是啟動(dòng)失敗
7.根據(jù)
requestCode
炉旷,resultWho
,ActivityInfo
等關(guān)鍵信息生成一個(gè)新的ActivityRecord
進(jìn)程優(yōu)先級(jí)
說起進(jìn)程叉讥,大致分為如下幾個(gè)adj優(yōu)先級(jí)級(jí)別:
注意每個(gè)版本的都可能數(shù)值不一樣窘行,這里是Android 9.0版本的:
ADJ級(jí)別 | 取值 | 解釋 |
---|---|---|
UNKNOWN_ADJ | 1001 | 一般是指緩存進(jìn)程也就是空進(jìn)程 |
CACHED_APP_MAX_ADJ | 906 | 不可見進(jìn)程的adj最大值 |
CACHED_APP_MIN_ADJ | 900 | 不可見進(jìn)程的adj最小值 |
SERVICE_B_ADJ | 800 | B List中的Service(較老的、使用可能性更型疾帧) |
PREVIOUS_APP_ADJ | 700 | 上一個(gè)App的進(jìn)程(往往通過按返回鍵) |
HOME_APP_ADJ | 600 | Home 進(jìn)程 |
SERVICE_ADJ | 500 | 包含Service的服務(wù)進(jìn)程 |
HEAVY_WEIGHT_APP_ADJ | 400 | 后臺(tái)的重量級(jí)進(jìn)程罐盔,system/rootdir/init.rc文件中設(shè)置 |
BACKUP_APP_ADJ | 300 | 備份進(jìn)程 |
PERCEPTIBLE_APP_ADJ | 200 | 可感知進(jìn)程(后臺(tái)服務(wù)播放音樂等) |
VISIBLE_APP_ADJ | 100 | 可見進(jìn)程 |
FOREGROUND_APP_ADJ | 0 | 前臺(tái)進(jìn)程 |
PERSISTENT_SERVICE_ADJ | -700 | 關(guān)聯(lián)著系統(tǒng)或persistent進(jìn)程 |
PERSISTENT_PROC_ADJ | -800 | 系統(tǒng)persistent進(jìn)程,比如telephony電話 |
SYSTEM_ADJ | -900 | 系統(tǒng)進(jìn)程 |
NATIVE_ADJ | -1000 | native 進(jìn)程救崔,不受系統(tǒng)管控 如從init.cpp中fork出來的,如內(nèi)核線程等等 |
總結(jié)下來惶看,面試中常問的Android中進(jìn)程優(yōu)先級(jí),一般可以分為如下幾種:
- 1.前臺(tái)進(jìn)程
- 2.可視進(jìn)程
- 3.服務(wù)進(jìn)程
- 4.后臺(tái)進(jìn)程
- 5.空進(jìn)程
從上至下六孵,進(jìn)程重要的等級(jí)越來越低纬黎,等級(jí)越低的adj數(shù)值越高,越高adj的數(shù)值越有可能被lmk
也就是lowmemorykiller 進(jìn)程通過某種策略殺掉劫窒。
對(duì)應(yīng)Android系統(tǒng)來說本今,UNKNOWN_ADJ
說明此時(shí)進(jìn)程的優(yōu)先級(jí)不明確,在調(diào)整adj的時(shí)候主巍,并不會(huì)通知lmk
進(jìn)程處理這個(gè)進(jìn)程冠息。
把這5個(gè)進(jìn)程等級(jí)拆分出來稍微解釋一下。所有調(diào)整adj數(shù)值都在computeOomAdjLocked
方法中
前臺(tái)進(jìn)程
是指當(dāng)前用戶必須執(zhí)行的進(jìn)程孕索。只有進(jìn)程真的沒內(nèi)存了逛艰,才會(huì)殺掉。一般是指adj等級(jí)為FOREGROUND_APP_ADJ
if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app.runningRemoteAnimation) {
...
} else if (app.instr != null) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app.executingServices.size() > 0) {
.
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app == TOP_APP) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
}
...
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
}
從上面可知搞旭,滿足前臺(tái)進(jìn)程的的情況如下:
- 1.正在交互的Activity瓮孙,也就是當(dāng)前的Activity正在onResume的生命周期
- 2.某個(gè)進(jìn)程正在被profile監(jiān)聽
- 3.某個(gè)Service綁定到用戶正在交互的Activity
- 4.某個(gè)進(jìn)程擁有并執(zhí)行了調(diào)用了
startForeground
的前臺(tái)服務(wù) - 5.某個(gè)進(jìn)程的廣播接收器正在接受消息
- 6.如果某個(gè)非系統(tǒng)進(jìn)程的ContentProvider的進(jìn)程正在被依賴其他進(jìn)程依賴獲取數(shù)據(jù),也是前臺(tái)進(jìn)程
- 7.擁有正執(zhí)行一個(gè)生命周期回調(diào)的 Service(onCreate()选脊、onStart() 或 onDestroy())
可見進(jìn)程
雖然沒有任何前臺(tái)的組件(指交互中的Activity,接收消息中的Receiver脸甘,被依賴獲取數(shù)據(jù)的CP恳啥,前臺(tái)服務(wù)等),但是依然會(huì)影響屏幕上的內(nèi)容丹诀。在這里是指VISIBLE_APP_ADJ
else if (app.runningRemoteAnimation) {
adj = ProcessList.VISIBLE_APP_ADJ;
...
}
if (r.visible) {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
...
}
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
...
if (adj > ProcessList.VISIBLE_APP_ADJ) {
newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
} else {
newAdj = adj;
}
...
}
- 1.擁有不再前臺(tái)钝的,但是可見也就是onPause的Activity
- 2.擁有或者綁定到前臺(tái)或者可見Activity的Service
- 3.正在執(zhí)行遠(yuǎn)程組件動(dòng)畫的進(jìn)程
服務(wù)進(jìn)程
一般是指與用戶所見內(nèi)容沒有直接的關(guān)聯(lián)翁垂,但是他們通常正在執(zhí)行用戶關(guān)心的任務(wù)(如后臺(tái)播放音樂,或者從網(wǎng)絡(luò)下載數(shù)據(jù))硝桩。
這里的adj是指 PERCEPTIBLE_APP_ADJ
if (r.visible) {
...
} else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pause-activity";
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
app.adjType = "pause-activity";
}
if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
app.cached = false;
app.empty = false;
foregroundActivities = true;
} else if (r.isState(ActivityState.STOPPING)) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stop-activity";
}
...
app.cached = false;
app.empty = false;
foregroundActivities = true;
} else {
...
}
}
- 1.不可見的Activity沿猜,并且是正在執(zhí)行onPause或者onPause執(zhí)行完畢
- 2.不可見的Activity,且是正在執(zhí)行onStop
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.foregroundServices) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.hasOverlayUi) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
app.cached = false;
app.adjType = "has-overlay-ui";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (app.forcingToImportant != null) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
app.cached = false;
app.adjType = "force-imp";
app.adjSource = app.forcingToImportant;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
3.adj優(yōu)先級(jí)低于
PERCEPTIBLE_APP_ADJ
碗脊,且比 擁有前臺(tái)服務(wù)進(jìn)程的優(yōu)先級(jí)低啼肩,則判斷是否持有前臺(tái)服務(wù),持有也會(huì)設(shè)置為PERCEPTIBLE_APP_ADJ
衙伶;如果當(dāng)前的進(jìn)程在執(zhí)行OverlayUi
也會(huì)設(shè)置為PERCEPTIBLE_APP_ADJ
祈坠。4.adj優(yōu)先級(jí)低于
PERCEPTIBLE_APP_ADJ
,且進(jìn)程狀態(tài)等級(jí)低于PROCESS_STATE_TRANSIENT_BACKGROUND
正在運(yùn)行的后臺(tái)服務(wù)的進(jìn)程,此時(shí)發(fā)現(xiàn)ProcessRecord
持有一個(gè)forcingToImportant
的token矢劲。這個(gè)token的設(shè)置實(shí)際是當(dāng)我們需要顯示Toast時(shí)候調(diào)用NotificationManagerService
的enqueueToast
入隊(duì)排序顯示吐司赦拘,為了顯示Toast
此時(shí)Android系統(tǒng)為了可以正常顯示,就會(huì)調(diào)用keepProcessAliveIfNeededLocked
設(shè)置進(jìn)程對(duì)應(yīng)的token
保證進(jìn)程在最低限度的存活芬沉。5.通過startService正在運(yùn)行的進(jìn)程.在這些進(jìn)程中找到那些最近顯示過ui的但是現(xiàn)在沒有顯示的躺同,或者此時(shí)沒有顯示ui進(jìn)程且沒有顯示toast的進(jìn)程,都降級(jí)為
PERCEPTIBLE_APP_ADJ
.
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
...
} else {
int newAdj;
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
...
} else {
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
}
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
...
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
} else {
newAdj = adj;
}
}
if (!client.cached) {
app.cached = false;
}
if (adj > newAdj) {
adj = newAdj;
adjType = "service";
}
}
}
}
}
}
后臺(tái)進(jìn)程
后臺(tái)進(jìn)程對(duì)用戶體驗(yàn)沒有任何影響丸逸,因此進(jìn)程可能會(huì)隨時(shí)回收掉這種進(jìn)程蹋艺,以獲得更多的內(nèi)存。通常會(huì)有很多后臺(tái)進(jìn)程正在運(yùn)行椭员,這些進(jìn)程都會(huì)保存在我剛剛說的LRU表中车海。如果Activity正常的執(zhí)行了生命周期并且緩存了狀態(tài),當(dāng)終止進(jìn)程時(shí)不會(huì)產(chǎn)生明顯用戶體驗(yàn)的影響隘击,當(dāng)通過導(dǎo)航重新打開侍芝,Activity將會(huì)讀取緩存并可見。
在這里adj是指從BACKUP_APP_ADJ
一直到SERVICE_B_ADJ
中間埋同。但是只有HOME_APP_ADJ
桌面進(jìn)程例外州叠。這個(gè)過程有什么魔法呢?實(shí)際上是在lmkd
進(jìn)程通信到lowmemorykiller
內(nèi)核模塊(驅(qū)動(dòng))之前凶赁,對(duì)600
數(shù)值對(duì)應(yīng)的adj數(shù)值進(jìn)行了特殊處理咧栗,強(qiáng)制設(shè)置為200
.
/system/core/lmkd/lmkd.c
static void cmd_procprio(LMKD_CTRL_PACKET packet) {
struct proc *procp;
char path[80];
char val[20];
int soft_limit_mult;
struct lmk_procprio params;
lmkd_pack_get_procprio(packet, ¶ms);
if (params.oomadj < OOM_SCORE_ADJ_MIN ||
params.oomadj > OOM_SCORE_ADJ_MAX) {
ALOGE("Invalid PROCPRIO oomadj argument %d", params.oomadj);
return;
}
snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
snprintf(val, sizeof(val), "%d", params.oomadj);
writefilestring(path, val);
if (use_inkernel_interface)
return;
if (low_ram_device) {
if (params.oomadj >= 900) {
soft_limit_mult = 0;
} else if (params.oomadj >= 800) {
soft_limit_mult = 0;
} else if (params.oomadj >= 700) {
soft_limit_mult = 0;
} else if (params.oomadj >= 600) {
// Launcher should be perceptible, don't kill it.
params.oomadj = 200;
soft_limit_mult = 1;
} else if (params.oomadj >= 500) {
soft_limit_mult = 0;
} else if (params.oomadj >= 400) {
soft_limit_mult = 0;
} else if (params.oomadj >= 300) {
soft_limit_mult = 1;
} else if (params.oomadj >= 200) {
soft_limit_mult = 2;
} else if (params.oomadj >= 100) {
soft_limit_mult = 10;
} else if (params.oomadj >= 0) {
soft_limit_mult = 20;
} else {
// Persistent processes will have a large
// soft limit 512MB.
soft_limit_mult = 64;
}
snprintf(path, sizeof(path),
"/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
params.uid, params.pid);
snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
writefilestring(path, val);
}
procp = pid_lookup(params.pid);
if (!procp) {
procp = malloc(sizeof(struct proc));
if (!procp) {
// Oh, the irony. May need to rebuild our state.
return;
}
procp->pid = params.pid;
procp->uid = params.uid;
procp->oomadj = params.oomadj;
proc_insert(procp);
} else {
proc_unslot(procp);
procp->oomadj = params.oomadj;
proc_slot(procp);
}
}
注意這里面的oomadj參數(shù)就是設(shè)置給lowmemorykiller 驅(qū)動(dòng)參數(shù)。在Android的Linux內(nèi)核中虱肄,每一個(gè)task_struct都包含了一個(gè)signal_struct
致板,其中就包含了進(jìn)程的優(yōu)先級(jí)oom_score_adj
。
空進(jìn)程
就是已經(jīng)什么都不存了咏窿,存儲(chǔ)只是緩存起來的進(jìn)程對(duì)象斟或,縮短下次在其中運(yùn)行組件所需的啟動(dòng)時(shí)間。
代表的adj數(shù)值是CACHED_APP_MIN_ADJ
到CACHED_APP_MAX_ADJ
lmk lowmemorykiller 驅(qū)動(dòng)原理
稍微總結(jié)一下lmkd守護(hù)進(jìn)程 是如何根據(jù)adj殺死無用進(jìn)程的集嵌。
如下圖:
整個(gè)lmk的流程需要從這幾個(gè)方向上理解萝挤。調(diào)整adj的時(shí)機(jī)有兩個(gè):
- 1.WMS的配置發(fā)生了配置御毅,此時(shí)就會(huì)調(diào)用
updateOomLevels
刷新每一個(gè)進(jìn)程的OOM等級(jí)核心計(jì)算方式如下:
private final int[] mOomAdj = new int[] {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
};
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final int[] mOomMinFreeLow = new int[] {
12288, 18432, 24576,
36864, 43008, 49152
};
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final int[] mOomMinFreeHigh = new int[] {
73728, 92160, 110592,
129024, 147456, 184320
};
// The actual OOM killer memory levels we are using.
private final int[] mOomMinFree = new int[mOomAdj.length];
首先,lmk只會(huì)處理FOREGROUND_APP_ADJ
,VISIBLE_APP_ADJ
,PERCEPTIBLE_APP_ADJ
,BACKUP_APP_ADJ
怜珍,CACHED_APP_MIN_ADJ
,CACHED_APP_MAX_ADJ
這6個(gè)級(jí)別的adj對(duì)應(yīng)的進(jìn)程端蛆。
每一次WMS的配置發(fā)生了變更,也就是屏幕相關(guān)的信息發(fā)生了變化酥泛,每一個(gè)進(jìn)程可用的最小內(nèi)存也會(huì)隨之發(fā)生變化今豆,計(jì)算公式如下:
LMK殺死進(jìn)程的閾值 = mOomMinFreeLow[對(duì)應(yīng)adj等級(jí)在mOomAdj的index] + (mOomMinFreeHigh[對(duì)應(yīng)adj等級(jí)在mOomAdj的index] - mOomMinFreeLow[對(duì)應(yīng)adj等級(jí)在mOomAdj的index])* scale
比如說:
此時(shí)是CACHED_APP_MAX_ADJ,在mOomMinFreeLow對(duì)應(yīng)的內(nèi)存是49152揭璃,在mOomMinFreeHigh對(duì)應(yīng)的是184320晚凿,則:49152+(184320-49152)*scale
這個(gè)scale數(shù)值的計(jì)算是根據(jù)屏幕狀態(tài)變化而變化:
scaleMem(內(nèi)存系數(shù)) = (系統(tǒng)的總內(nèi)存(單位MB) - 350)/ 350
scaleDisp(屏幕內(nèi)存系數(shù)) = ((屏幕寬*屏幕高) - (480 * 800)) / ((1280 * 800) - (480 * 800))
實(shí)際上第一個(gè)內(nèi)存系數(shù)就是獲取當(dāng)前內(nèi)存以350M為一個(gè)單位看看還有多少份;第二個(gè)屏幕內(nèi)存系數(shù)是看看一個(gè)屏幕下總像素的內(nèi)存進(jìn)行均值化 (有興趣可以看看線性回歸與梯度下降)從而獲得屏幕像素歸一到(480 * 800) (最小屏幕大小)和(1280 * 800) 最大屏幕大小(很明顯現(xiàn)實(shí)中比最大的大瘦馍,比最小的小比比皆是)歼秽,從而獲得一個(gè)合適的像素內(nèi)存系數(shù)。
比較兩者取較大的數(shù)值
scale = scaleMem > scaleDisp ? scaleMem : scaleDisp
最后把計(jì)算出來的對(duì)應(yīng)的adj對(duì)應(yīng)的最小內(nèi)存保存到mOomMinFree數(shù)組中發(fā)送到lowmemorykiller驅(qū)動(dòng)中緩存起來情组。
- 2.當(dāng)進(jìn)程中四大組件的行為發(fā)生了變更燥筷,則會(huì)每一個(gè)進(jìn)程對(duì)應(yīng)adj數(shù)值。此時(shí)會(huì)先通過socket通信到
lmkd
守護(hù)進(jìn)程中院崇,此時(shí)會(huì)通過Linux的cgroup
把當(dāng)前對(duì)應(yīng)的內(nèi)存限額寫入對(duì)應(yīng)的進(jìn)程中肆氓。等到內(nèi)核需要回收的時(shí)候,就會(huì)通過lowkmemorykiller
遍歷找到最大的rss內(nèi)存底瓣,最大的adj通過發(fā)送中斷信號(hào)SIGKILL
殺死進(jìn)程谢揪。
Activity 棧的變化
要徹底弄明白Activity的棧變化需要了解如下數(shù)據(jù)結(jié)構(gòu),可以閱讀我寫過的WMS在Activity啟動(dòng)中的職責(zé)(二)一文捐凭,里面介紹了不僅僅是Activity啟動(dòng)時(shí)候拨扶,對(duì)應(yīng)棧的數(shù)據(jù)結(jié)構(gòu),還對(duì)應(yīng)了WMS如何控制這些數(shù)據(jù)結(jié)構(gòu)的顯示:
先從這個(gè)圖中關(guān)鍵的四個(gè)的數(shù)據(jù)結(jié)構(gòu)開始說起:
-
ActivityDisplay
代表每一個(gè)Activity顯示的顯示屏茁肠,內(nèi)持有邏輯顯示屏對(duì)應(yīng)的id患民。這個(gè)對(duì)象將會(huì)持有三個(gè)核心的數(shù)據(jù)結(jié)構(gòu)DisplayWindowController
,DisplayContent
,ActivityStack
.前兩者控制整個(gè)棧對(duì)應(yīng)的顯示區(qū)域如何擺放.后者則是以一個(gè)應(yīng)用進(jìn)程的維度控制棧
-
-
ActivityStack
是指進(jìn)程中有多少個(gè)Activity的棧。這個(gè)棧持有了一個(gè)mHistory
集合垦梆。這個(gè)棧才是正常開發(fā)中接觸到的棧匹颤。
-
3.TaskRecord 就是我們開發(fā)中接觸的棧,這個(gè)棧持有了taskid托猩,affinity等標(biāo)識(shí)參數(shù)印蓖。其中持有一個(gè)核心數(shù)據(jù)結(jié)構(gòu)mActivities的集合
mActivities
。4.ActivityRecord 實(shí)際上就是Activity在AMS中標(biāo)示對(duì)象京腥。系統(tǒng)通過持有ActivityRecord從而得知每一個(gè)應(yīng)用進(jìn)程中每一個(gè)Activity的狀態(tài)另伍。
如下圖:
對(duì)于我們開發(fā)者來說只有TaskRecord才是可見的。
理解了這些之后,在方法startActivityUnchecked
會(huì)處理絕大部分的關(guān)于Task相關(guān)的操作摆尝。
回顧一下Activity四大啟動(dòng)模式:
- 1.standard 意味著默認(rèn)啟動(dòng)方式。繼承上一個(gè)Activity對(duì)應(yīng)的Task進(jìn)行啟動(dòng)
- 2.singleTop 如果Activity處于棧頂則不需要?jiǎng)?chuàng)建因悲,不在棧頂則創(chuàng)建新的堕汞。意味這這里的棧頂也就是TaskRecord的mActivities處于末尾頂部
- 3.singleTask 是指棧內(nèi)唯一,此時(shí)會(huì)從TaskRecord的mActivities中查找能否有復(fù)用的ActivityRecord
- 4.singleInstance 這個(gè)是指新建一個(gè)TaskRecord保存在mTaskHistory中晃琳,并新建一個(gè)新的ActivityRecord讯检。
實(shí)際上AMS,并不是根據(jù)這四個(gè)啟動(dòng)模式進(jìn)行處理的卫旱。而是這四個(gè)啟動(dòng)模式人灼,會(huì)轉(zhuǎn)化成Intent中對(duì)應(yīng)的flag進(jìn)行出來。
其實(shí)很簡(jiǎn)單顾翼,如果我們忽略了分屏操作的行為投放,實(shí)際上在AMS眼里可以把啟動(dòng)帶上的flag分為如下四類:
- 1.如果是啟動(dòng)的flag打上了
FLAG_ACTIVITY_NEW_TASK
,調(diào)用setTaskFromReuseOrCreateNewTask
- 2.繼承上一個(gè)
ActivityRecord
對(duì)應(yīng)的TaskRecord
調(diào)用setTaskFromSourceRecord
- 3.不繼承上一個(gè)
ActivityRecord
的TaskRecord
,但是因?yàn)橹付?code>TaskRecord的affinity
,id
等方式提前得知了對(duì)應(yīng)的TaskRecord
,從而移動(dòng)到另一個(gè)TaskRecord
調(diào)用setTaskFromInTask
- 4.其他模式 調(diào)用
setTaskToCurrentTopOrCreateNewTask
第三點(diǎn)适贸,是系統(tǒng)內(nèi)部調(diào)用startActivityInPackage
時(shí)候明確知道TaskRecord是什么灸芳。我們不去討論。
setTaskFromReuseOrCreateNewTask
這個(gè)方法就是專門處理FLAG_ACTIVITY_NEW_TASK
標(biāo)志位的拜姿。
在執(zhí)行這個(gè)判斷之前烙样,會(huì)調(diào)用computeLaunchingTaskFlags
方法判斷調(diào)用startActivity的調(diào)用者,是否存在啟動(dòng)的Activity對(duì)象且沒有確定的TaskRecord(mInTask)蕊肥,此時(shí)就是谒获。
-沒有復(fù)用的TaskRecord
: 在setTaskFromReuseOrCreateNewTask
這個(gè)方法就會(huì)創(chuàng)建一個(gè)新的TaskRecord
.在準(zhǔn)備的步驟,已經(jīng)找到對(duì)應(yīng)的ActivityRecord
.壁却,或者創(chuàng)建一個(gè)全新的ActivityRecord
.就會(huì)調(diào)用addOrReparentStartingActivity
綁定這個(gè)全新的TaskRecord
.
- 存在復(fù)用
TaskRecord
:則直接調(diào)用addOrReparentStartingActivity
重新綁定TaskRecord
.從而實(shí)現(xiàn)棧內(nèi)唯一批狱。指的注意的是,如果此時(shí)的launchMode
是LAUNCH_SINGLE_INSTANCE
或者LAUNCH_SINGLE_TASK
則強(qiáng)制把對(duì)應(yīng)的登錄flag添加一個(gè)FLAG_ACTIVITY_NEW_TASK
.
setTaskFromSourceRecord
這個(gè)過程中儒洛,就會(huì)獲得調(diào)用者ActivityRecord
的TaskRecord
以及ActivityStack
,新的ActivityRecord并準(zhǔn)備繼承這些對(duì)象精耐。
- 判斷是否帶上
FLAG_ACTIVITY_CLEAR_TOP
標(biāo)志位且不需要添加到TaskRecord,帶則調(diào)用TaskRecord
的performClearTaskLocked
調(diào)用這個(gè)方法調(diào)用之前復(fù)用ActivityRecord
之前的所有Activity的finish的方法琅锻。
- 判斷是否帶上
2.并把對(duì)應(yīng)的
ActivityStack
卦停,TaskRecord
移動(dòng)到集合的末尾,作為當(dāng)前的焦點(diǎn)恼蓬。3.
addOrReparentStartingActivity
綁定或者新增到TaskRecord中
setTaskToCurrentTopOrCreateNewTask
private void setTaskToCurrentTopOrCreateNewTask() {
mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
if (mDoResume) {
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.getTopActivity();
final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
}
其他情況就是拿到焦點(diǎn)的ActivityStack
后再拿到頂部運(yùn)行的TaskRecord
惊完,把新的ActivityRecord
綁定起來。
Activity跨進(jìn)程啟動(dòng)
在方法realStartActivityLocked
中真正的開始進(jìn)行跨進(jìn)程通信处硬,在繼續(xù)聊之前看看幾個(gè)重要的對(duì)象:
ClientTransaction 是AMS通信到App應(yīng)用進(jìn)程的核心對(duì)象小槐。
- 1.ClientTransaction 客戶端事務(wù)控制者
- 2.ClientLifecycleManager 客戶端的生命周期事務(wù)控制者
- 3.TransactionExecutor 遠(yuǎn)程通信事務(wù)執(zhí)行者
- 4.LaunchActivityItem 遠(yuǎn)程App端的onCreate生命周期事務(wù)
- 5.ResumeActivityItem 遠(yuǎn)程App端的onResume生命周期事務(wù)
- 6.PauseActivityItem 遠(yuǎn)程App端的onPause生命周期事務(wù)
- 7.StopActivityItem 遠(yuǎn)程App端的onStop生命周期事務(wù)
- 8.DestroyActivityItem 遠(yuǎn)程App端onDestroy生命周期事務(wù)。
- 9.ClientTransactionHandler App端對(duì)ClientTransaction的處理。
LaunchActivityItem
LaunchActivityItem 通信到在AppThread做了如下事情:
- 1.反射生成Activity實(shí)例
- 2.獲取當(dāng)前的應(yīng)用的Application對(duì)象并且調(diào)用attach綁定
- 3.最后通過Instrument調(diào)用callActivityOnCreate調(diào)用到Activity實(shí)例中的onCreate方法
ResumeActivityItem
- 1.調(diào)用
ActivityThread
的handleStartActivity
,執(zhí)行Activity
的onStart
方法 - 2.調(diào)用
ActivityThread
的performResumeActivity
- 3.如果pendingIntent不為空凿跳,則以此執(zhí)行執(zhí)行
onNewIntent
,onActivityResult
- 4.執(zhí)行
Activity
的onResume
- 5.執(zhí)行View的繪制流程
- 6.執(zhí)行handler的idle事件件豌,這個(gè)事件就是
Idler
對(duì)象。關(guān)于idle相關(guān)的內(nèi)容可以閱讀Handler與相關(guān)系統(tǒng)調(diào)用的剖析(上).這個(gè)事件就是Handler沒有什么重要事件執(zhí)行的控嗜,執(zhí)行的內(nèi)容就是activityIdle
這個(gè)方法就會(huì)調(diào)用所有不可見Activity的onStop
PauseActivityItem
- 1.Android3.0之前調(diào)用
callActivityOnSaveInstanceState
方法保存當(dāng)前Activity
的狀態(tài) - 2.調(diào)用
Activity
的onPause
- 3.此時(shí)一旦判斷當(dāng)前ActivityRecord已經(jīng)綁定了App端的數(shù)據(jù)茧彤,說明已經(jīng)啟動(dòng)了,并且當(dāng)前的ActivityRecord的visible為false疆栏,或者點(diǎn)擊了鎖屏使其睡眠曾掂,都會(huì)調(diào)用addToStopping.到activityIdle方法就會(huì)執(zhí)行Activity的onStop,因此如果是可見的dialog壁顶,由于此時(shí)Activity還是可見珠洗,因此不會(huì)走到onStop方法
StopActivityItem
- 1.調(diào)用過
ActivityThread
的handleStopActivity方法 - 2.如果沒有調(diào)用過
onPause
則調(diào)用onPause
- 3.調(diào)用
Activity
的onStop
- 4.等待SP寫入磁盤
- 5.執(zhí)行AMS的activityStopped,在
activityStoppedLocked
里面判斷ActivityRecord是否通過makeFinishingLocked設(shè)置了finishing為true若专,從而判斷是否需要執(zhí)行后續(xù)的周期许蓖。
DestroyActivityItem
當(dāng)調(diào)用了Activity的finish
方法后,就會(huì)跨進(jìn)程調(diào)用的finishActivity
:
1.當(dāng)前要finish的Activity剛好就是當(dāng)前的正在交互的Activity富岳,則調(diào)用
onPause
和onStop
,調(diào)用ActivityStack
的destroyActivityLocked
2.當(dāng)finish的Activity不是onPause蛔糯,嘗試調(diào)用
finishCurrentActivityLocked
,finish對(duì)應(yīng)的Activity,接著會(huì)嘗試的調(diào)用addToStopping窖式,會(huì)調(diào)到onStop方法蚁飒,接著也會(huì)調(diào)用destroyActivityLocked。3.執(zhí)行
DestroyActivityItem
中對(duì)應(yīng)的跨進(jìn)程操作4.調(diào)用Activity的OnDestroy
5.將會(huì)清空Activity中設(shè)置的window數(shù)據(jù)以及設(shè)置的ContentView
6.最后通過activityDestroyed通知AMS
onRestart
肯定有人覺得奇怪萝喘,七大聲明周期之一的onRestart呢淮逻?他其實(shí)和onStart一樣隱藏在TransactionExecutor 中。
來看看/frameworks/base/core/java/android/app/servertransaction/TransactionExecutorHelper.java
:
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
if (start == UNDEFINED || finish == UNDEFINED) {
throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
}
if (start == ON_RESTART || finish == ON_RESTART) {
throw new IllegalArgumentException(
"Can't start or finish in intermittent RESTART state");
}
if (finish == PRE_ON_CREATE && start != finish) {
throw new IllegalArgumentException("Can only start in pre-onCreate state");
}
mLifecycleSequence.clear();
if (finish >= start) {
// just go there
...
} else { // finish < start, can't just cycle down
if (start == ON_PAUSE && finish == ON_RESUME) {
// Special case when we can just directly go to resumed state.
mLifecycleSequence.add(ON_RESUME);
} else if (start <= ON_STOP && finish >= ON_START) {
// Restart and go to required state.
// Go to stopped state first.
for (int i = start + 1; i <= ON_STOP; i++) {
mLifecycleSequence.add(i);
}
// Restart
mLifecycleSequence.add(ON_RESTART);
// Go to required state
for (int i = ON_START; i <= finish; i++) {
mLifecycleSequence.add(i);
}
} else {
// Relaunch and go to required state
// Go to destroyed state first.
for (int i = start + 1; i <= ON_DESTROY; i++) {
mLifecycleSequence.add(i);
}
// Go to required state
for (int i = ON_CREATE; i <= finish; i++) {
mLifecycleSequence.add(i);
}
}
}
...
return mLifecycleSequence;
}
注意這里的參數(shù)start是指當(dāng)前Activity的狀態(tài)阁簸,finish是指經(jīng)過TransactionExecutor執(zhí)行后爬早,每一個(gè)ActivityLifecycleItem
對(duì)應(yīng)的目標(biāo)Activity需要達(dá)到什么聲明周期。
1.如果當(dāng)前的Activity是
ON_PAUSE
狀態(tài)启妹,目標(biāo)是ON_RESUME
筛严,此時(shí)只需要執(zhí)行一個(gè)ON_RESUME
2.如果此時(shí)的狀態(tài)是
ON_STOP
之后的狀態(tài),且目標(biāo)是ON_START
.一般來說此時(shí)都是執(zhí)行的是ResumeActivityItem
需要從AMS讓此時(shí)的Activity轉(zhuǎn)化為可見饶米。此時(shí)的Activity
已經(jīng)執(zhí)行了onStop桨啃,就會(huì)把小于ON_STOP
的狀態(tài)添加進(jìn)來(沒有就跳過了),再把ON_RESTART
聲明周期添加進(jìn)來,最后把onStart
和onResume
(因?yàn)?code>ResumeActivityItem 目標(biāo)就是onResume
)添加進(jìn)來3.最后到達(dá)了TransactionExecutor中執(zhí)行每一個(gè)
ActivityLifecycleItem
的生命周期檬输,從而執(zhí)行了ActivityThread的onRestart
后執(zhí)行照瘾,onStart
,onResume
實(shí)際案例
有一道常見的面試題:
- Activity A 啟動(dòng) Activity B 聲明周期怎么執(zhí)行
- Activity B 在onCreate,onResume執(zhí)行finish是怎么執(zhí)行聲明周期的丧慈。
第一種情況下:A啟動(dòng)了B析命。
此時(shí)A會(huì)先執(zhí)行PauseActivityItem,從而執(zhí)行onPause,此時(shí)AMS會(huì)阻塞住不會(huì)前往執(zhí)行B的啟動(dòng)。
onPause執(zhí)行結(jié)束之后鹃愤,就會(huì)繼續(xù)執(zhí)行A的onCreate簇搅,onStart,onResume,接著執(zhí)行一個(gè)idle事件,通知AMS執(zhí)行所有不可見的Activity的onStop
,如下圖:
2020-09-12 22:44:20.745 9287-9287/com.yjy.superjsbridge E/A: onStart
2020-09-12 22:44:20.747 9287-9287/com.yjy.superjsbridge E/A: onResume
2020-09-12 22:44:31.746 9287-9287/com.yjy.superjsbridge E/A: onPause
2020-09-12 22:44:31.768 9287-9287/com.yjy.superjsbridge E/B: onCreate
2020-09-12 22:44:32.598 9287-9287/com.yjy.superjsbridge E/B: onStart
2020-09-12 22:44:32.603 9287-9287/com.yjy.superjsbridge E/B: onResume
2020-09-12 22:44:33.083 9287-9287/com.yjy.superjsbridge E/A: onStop
2020-09-12 22:54:31.631 9287-9287/com.yjy.superjsbridge E/B: onPause
2020-09-12 22:54:31.688 9287-9287/com.yjy.superjsbridge E/B: onStop
一旦熄掉屏幕后昼浦,重新打開馍资,或者從Home/其他App回來后就會(huì)執(zhí)行:
2020-09-12 23:00:14.342 9287-9287/com.yjy.superjsbridge E/B: onRestart
2020-09-12 23:00:14.418 9287-9287/com.yjy.superjsbridge E/B: onStart
2020-09-12 23:00:14.433 9287-9287/com.yjy.superjsbridge E/B: onResume
第二種:Activity A 在onCreate,onResume執(zhí)行finish是怎么執(zhí)行聲明周期的关噪。其實(shí)就是考察了對(duì)finishActivityLocked
的理解。
當(dāng)調(diào)用了finish之后乌妙,會(huì)執(zhí)行如下方法:
if (mResumedActivity == r) {
....
r.setVisibility(false);
if (mPausingActivity == null) {
startPausingLocked(false, false, null, pauseImmediately);
}
if (endTask) {
mService.getLockTaskController().clearLockedTask(task);
}
} else if (!r.isState(PAUSING)) {
....
final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
: FINISH_AFTER_PAUSE;
final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
"finishActivityLocked") == null;
....
return removedActivity;
} else {
}
只分為兩種情況:
當(dāng)前的Activity在onResume使兔,此時(shí)設(shè)置了visible為false,并開始調(diào)用onPause方法藤韵。所以就會(huì)調(diào)用
onPause
,當(dāng)執(zhí)行完后虐沥,就會(huì)調(diào)用completePauseLocked
方法,此時(shí)是不可見的泽艘,就會(huì)添加到addToStop對(duì)象欲险,并且執(zhí)行onStop的方法以及onDestory-
如果此時(shí)不是正在執(zhí)行
PAUSING
。則根據(jù)是否顯示來決定是finish的方法是可視化之后再finish(FINISH_AFTER_VISIBLE
)匹涮,另一個(gè)是pause之后在finish(FINISH_AFTER_PAUSE
)天试。-
FINISH_AFTER_VISIBLE
則通過startPausingLocked
調(diào)用addToStop
,通知AMS的Handler執(zhí)行activityIdleInternalLocked
方法然低,這個(gè)方法就是執(zhí)行ActivityThread的onStop的入口喜每。在ActivityThread
中會(huì)校驗(yàn)onPause
是否執(zhí)行,沒執(zhí)行過則執(zhí)行雳攘,最后執(zhí)行onStop
带兜,并在activityIdleInternalLocked
的后半段立即返回來執(zhí)行finishActivityLocked
方法,此時(shí)就是FINISH_AFTER_PAUSE
的方式
-
FINISH_AFTER_PAUSE
把狀態(tài)設(shè)置為FINISHING
吨灭,調(diào)用destroyActivityLocked
開始真正執(zhí)行onDestroy周期刚照。發(fā)送一個(gè)Handler消息最后把ActivityRecord從TaskRecord 中移除,如果此時(shí)TaskRecord已經(jīng)不存在ActivityRecord喧兄,則從ActivityStack移除
都是在之前的文章詳細(xì)說過的无畔。
那么,放在這里:
- 如果B在onCreate執(zhí)行了onDestroy繁莹,此時(shí)走的就是
FINISH_AFTER_PAUSE
直接finish掉
2020-09-12 23:42:19.043 13942-13942/com.yjy.superjsbridge E/B: onCreate
2020-09-12 23:42:19.921 13942-13942/com.yjy.superjsbridge E/B: onDestroy
- onStart周期比較特殊檩互,因?yàn)閛nStart是跟在ResumeActivityItem中間走的,但是執(zhí)行到了執(zhí)行完了onStart就設(shè)置為finishing狀態(tài)咨演,導(dǎo)致onResume無法走下去闸昨。此時(shí)相當(dāng)于visible還沒有設(shè)置為true,走的是
FINISH_AFTER_PAUSE
,直接執(zhí)行onDestroy的周期,注意下面這段代碼,此時(shí)根據(jù)當(dāng)前ActivityClientRecord
的標(biāo)志位來決定是否需要補(bǔ)充執(zhí)行onPause
饵较,和onStop
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = mActivities.get(token);
Class<? extends Activity> activityClass = null;
if (r != null) {
activityClass = r.activity.getClass();
r.activity.mConfigChangeFlags |= configChanges;
if (finishing) {
r.activity.mFinished = true;
}
performPauseActivityIfNeeded(r, "destroy");
if (!r.stopped) {
callActivityOnStop(r, false /* saveState */, "destroy");
}
...
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnDestroy(r.activity);
...
} catch (SuperNotCalledException e) {
...
} catch (Exception e) {
...
}
r.setState(ON_DESTROY);
}
mActivities.remove(token);
StrictMode.decrementExpectedActivityCount(activityClass);
return r;
}
注意拍嵌,每一次聲明周期的執(zhí)行后,都會(huì)調(diào)用如下方法:
public void setState(@LifecycleState int newLifecycleState) {
mLifecycleState = newLifecycleState;
switch (mLifecycleState) {
case ON_CREATE:
paused = true;
stopped = true;
break;
case ON_START:
paused = true;
stopped = false;
break;
case ON_RESUME:
paused = false;
stopped = false;
break;
case ON_PAUSE:
paused = true;
stopped = false;
break;
case ON_STOP:
paused = true;
stopped = true;
break;
}
}
能發(fā)現(xiàn)onCreate
執(zhí)行之后paused
和stopped
都是true,所以performDestroyActivity不會(huì)補(bǔ)充執(zhí)行onPause
,onStop
直接執(zhí)行onDestroy
.
如果是onStart
執(zhí)行之后,paused
為true,stopped
是false循诉,所以横辆,在`onDestroy補(bǔ)充執(zhí)行onStop
2020-09-12 23:49:07.902 15359-15359/com.yjy.superjsbridge E/B: onCreate
2020-09-12 23:49:08.066 15359-15359/com.yjy.superjsbridge E/B: onStart
2020-09-12 23:49:08.107 15359-15359/com.yjy.superjsbridge E/B: onStop
2020-09-12 23:49:08.107 15359-15359/com.yjy.superjsbridge E/B: onDestroy
如果A在onResume,onPause茄猫,onStop方法執(zhí)行finish,就會(huì)走FINISH_AFTER_VISIBLE
流程狈蚤,依次走完剩下的流程再走onDestroy.
onResume 中finish:
020-09-13 10:15:36.193 1071-1071/com.yjy.superjsbridge E/B: onCreate
2020-09-13 10:15:36.813 1071-1071/com.yjy.superjsbridge E/B: onStart
2020-09-13 10:15:36.818 1071-1071/com.yjy.superjsbridge E/B: onResume
2020-09-13 10:15:36.843 1071-1071/com.yjy.superjsbridge E/B: onPause
2020-09-13 10:15:36.860 1071-1071/com.yjy.superjsbridge E/A: onResume
2020-09-13 10:15:36.894 1071-1071/com.yjy.superjsbridge E/B: onStop
2020-09-13 10:15:36.895 1071-1071/com.yjy.superjsbridge E/B: onDestroy
onPause 中finish:
E/B: onPause
E/B: onStop
E/B: onDestroy
onStop 中finish:
2020-09-13 10:28:10.311 12235-12235/com.yjy.superjsbridge E/B: onPause
2020-09-13 10:28:10.385 12235-12235/com.yjy.superjsbridge E/B: onStop
2020-09-13 10:28:10.654 12235-12235/com.yjy.superjsbridge E/B: onDestroy
同理在onRestart也是類似的,因?yàn)辄c(diǎn)擊了Home等情況,所以已經(jīng)執(zhí)行過了onStop划纽,所以會(huì)繼續(xù)走完下面的周期:
2020-09-13 10:29:43.099 12412-12412/com.yjy.superjsbridge E/B: onRestart
2020-09-13 10:29:43.540 12412-12412/com.yjy.superjsbridge E/B: onDestroy
`