前言
Activity/Fragment/View 系列文章:
Android Activity 與View 的互動(dòng)思考
Android Activity 生命周期詳解及監(jiān)聽(tīng)
Android onSaveInstanceState/onRestoreInstanceState 原來(lái)要這么理解
Android Fragment 要你何用?
Android Activity/View/Window/Dialog/Fragment 深層次關(guān)聯(lián)(白話解析)
當(dāng)你編寫第一個(gè)Android "Hello World" 時(shí)坤按,已經(jīng)不知不覺(jué)地與Activity生命周期打交道待牵。這部分是是Android 最基礎(chǔ)的知識(shí)之一,也是面試的持づ福客,同時(shí)也是理解Jetpack 組件的基礎(chǔ)勤晚。
網(wǎng)上關(guān)于此的文章數(shù)不勝數(shù)枉层,但大部分只流于表象,沒(méi)有系統(tǒng)性分析赐写,看過(guò)之后容易忘卻鸟蜡。本系列將會(huì)著重分析由此衍生的一系列知識(shí)點(diǎn)。
通過(guò)本篇文章挺邀,你將了解到:
1揉忘、什么是生命周期?
2端铛、誰(shuí)是生命周期的幕后黑手泣矛?
3、如何感知生命周期
1禾蚕、什么是生命周期
這個(gè)名字并不是計(jì)算機(jī)獨(dú)創(chuàng)的術(shù)語(yǔ)您朽,任何有生命的東西都有周期,從出生到死亡换淆,以人為例:
這是一個(gè)人的成長(zhǎng)軌跡哗总,也是一個(gè)人的生命周期几颜,在不同的年齡段表現(xiàn)各異。
俗話說(shuō):人活一世讯屈,草木一秋蛋哭。
佛家說(shuō)的輪回,當(dāng)一個(gè)人入土為安涮母,假設(shè)有輪回具壮,在下一個(gè)輪回里再經(jīng)歷出生到死亡,這個(gè)人還是上一世的那個(gè)人嗎哈蝇?
同樣的草木凋謝了棺妓,在春天再長(zhǎng)出來(lái)時(shí),還是曾經(jīng)的它嗎炮赦?
不是怜跑,它們都是新的生命。
Activity 的生命周期
先來(lái)看官方經(jīng)典圖:
Activity 作為對(duì)象吠勘,它是有"生命的"性芬,類似人和草木,它的存活周期就是它的生命周期剧防。
為什么生命周期要分不同的階段植锉?
就像人一樣:
1、當(dāng)處在嬰兒階段峭拘,自己每天喝喝奶俊庇,沒(méi)事就哭鬧一下,大人就會(huì)安撫你鸡挠。
2辉饱、當(dāng)處在學(xué)生時(shí)代,就認(rèn)真做題拣展,大家把你當(dāng)小孩看待彭沼,不用你出門賺錢,景點(diǎn)都能給你學(xué)生票五折優(yōu)惠备埃。
3姓惑、當(dāng)處在工作時(shí)代,就好好搬磚按脚,老板會(huì)給你福報(bào)于毙。
4、...
同樣的乘寒,對(duì)于Activity 來(lái)說(shuō)望众,在不同的階段自己內(nèi)部所做的事情不同匪补,外部監(jiān)聽(tīng)到Activity的處在不同階段將會(huì)采取不同的措施伞辛。
總結(jié)來(lái)說(shuō):
生命周期分階段既是為了"生命體內(nèi)部"流轉(zhuǎn)的需要烂翰,也是為了讓外部知道"生命體"當(dāng)前所處的階段進(jìn)而做出相應(yīng)的決策。
與人蚤氏、草木一樣甘耿,當(dāng)Activity 經(jīng)歷了一個(gè)生命周期后,再次重建時(shí)已經(jīng)不是當(dāng)初的對(duì)象了竿滨。
Activity 生命周期不同階段
主要分為:
可以看出Create 對(duì)應(yīng) Destroy佳恬,Start對(duì)應(yīng)Stop,Resume對(duì)應(yīng)Pause于游。
既然每個(gè)階段都有回調(diào)毁葱,那么只需要重寫對(duì)應(yīng)的回調(diào)方法,添加打印即可測(cè)試不同的操作后Activity處在哪個(gè)階段贰剥。
接下來(lái)看看Activity 常見(jiàn)的切換場(chǎng)景:
Activity A 啟動(dòng)Activity B
圖上數(shù)字表示發(fā)生的順序倾剿,具有時(shí)間上的先后順序。
從Activity A 按Home回到桌面
回到桌面或者最近任務(wù)列表:
Activity B 按back 鍵/調(diào)用finish
此時(shí)Activity B處在棧頂位置蚌成,而Activity A 位于它之下前痘。
Pause 階段
上面列出的場(chǎng)景都是onPause-->onStop,那么Activity 是否存在只停留在onPause的階段担忧?
Pause階段是Activity 可見(jiàn)芹缔,但是沒(méi)有焦點(diǎn)因此無(wú)法和用戶交互。
可見(jiàn)意味著它的上面有Activity瓶盛,并且上面的Activity 是透明的最欠,才可以看見(jiàn)底下的Activity。
此種情況下惩猫,底下的Activity 處在Pause階段窒所。
如上圖,紅色區(qū)塊是新啟動(dòng)的Activity帆锋,該Activity 沒(méi)有全屏并且透明吵取,可以看到底下Activity 內(nèi)容,此時(shí)它處在Pause階段锯厢。
2皮官、誰(shuí)是生命周期的幕后黑手?
我們知道Android 是事件驅(qū)動(dòng)的实辑,通過(guò)Loop來(lái)循環(huán)執(zhí)行MessageQueue里的Message捺氢。
問(wèn)題來(lái)了:onCreate、onStart剪撬、onStop 是在同一個(gè)Message里執(zhí)行的嗎摄乒?
要弄清楚這個(gè)問(wèn)題,需要知道回調(diào)這些方法的堆棧。眾所周知馍佑,四大組件都是由AMS(Activity Manager Service)控制的斋否,而AMS 運(yùn)行在system_server 進(jìn)程,與咱們的App是不同的進(jìn)程拭荤,AMS 通過(guò)Binder 與各個(gè)App進(jìn)行通信茵臭。
不清楚的可移步:Android 四大組件通信核心
接下來(lái)探究AMS 如何控制Activity 生命周期回調(diào)的。
onCreate 調(diào)用堆棧
在onCreate()里打個(gè)斷點(diǎn)舅世,調(diào)用棧如下:
可以看出入口是在ActivityThread.java 類里旦委。
1、App進(jìn)程啟動(dòng)的時(shí)雏亚,將ApplicationThread 傳遞給AMS缨硝,類似向AMS 注冊(cè)回調(diào)。
2罢低、AMS 通過(guò)ApplicationThread 通知App Activity 的生命周期追葡。
3、App 切換到主線程執(zhí)行對(duì)應(yīng)的方法奕短,最終會(huì)執(zhí)行Activity 的onCreate()宜肉、onStart()、onResume()等方法翎碑。
其它階段的調(diào)用棧
與onCreate 類似谬返,onStart、onResume日杈、onPause遣铝、onStop、onDestroy 階段同樣經(jīng)歷了AMS--->App--->切換到主線程--->回調(diào)對(duì)應(yīng)方法莉擒。
為方便起見(jiàn)酿炸,省去AMS 過(guò)程,用圖表示如下:
由以上分析可知:
1涨冀、Activity 生命周期的幕后黑手是AMS填硕。
2、各個(gè)階段的調(diào)用棧很相似鹿鳖,只是變了方法名而已扁眯。
3、onCreate翅帜、onStart姻檀、onStop 不是在同一個(gè)Message里執(zhí)行的,但是都是在主線程執(zhí)行涝滴。
3绣版、如何感知生命周期
注冊(cè)監(jiān)聽(tīng)
知道了生命周期的來(lái)龍去脈胶台,要監(jiān)聽(tīng)生命周期就變得非常簡(jiǎn)單了,只需要在Activity 里重寫對(duì)應(yīng)階段的回調(diào)方法即可杂抽,這也是我們最基礎(chǔ)的選擇诈唬。
現(xiàn)在有個(gè)需求:監(jiān)聽(tīng)App處在前臺(tái)還是后臺(tái)?
Activity 處在后臺(tái)默怨,那么此時(shí)階段為Stop讯榕,回到前臺(tái)那么此時(shí)處會(huì)經(jīng)歷Start階段骤素,在進(jìn)入Start 階段時(shí)記錄+1匙睹,在進(jìn)入Stop階段時(shí)記錄-1。若最終結(jié)果記錄=1济竹,說(shuō)明App在前臺(tái)痕檬。
這么看來(lái),我們需要一個(gè)公共的Activity來(lái)進(jìn)行統(tǒng)一記錄送浊,每個(gè)新建的Activity 都繼承自它梦谜,這么做雖然能滿足需求,但也有弊端:一是工作量大袭景,二是也不靈活唁桩。
實(shí)際上還有更好的方式來(lái)全局監(jiān)聽(tīng)各個(gè)Activity 生命周期。
#Application.java
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
synchronized (mActivityLifecycleCallbacks) {
mActivityLifecycleCallbacks.add(callback);
}
}
Application.java 里有個(gè)方法耸棒,顧名思義用來(lái)注冊(cè)Activity 生命周期回調(diào)的荒澡,這個(gè)callback 會(huì)加入到回調(diào)List:mActivityLifecycleCallbacks 里。
先看看ActivityLifecycleCallbacks 的構(gòu)成:
它是個(gè)接口与殃,乍一看有很多方法单山,實(shí)際上都是有規(guī)律可循的,總結(jié)下來(lái)就是監(jiān)聽(tīng)了:
Create幅疼、Start米奸、Resume、Pause爽篷、Stop悴晰、Destroy、SaveInstanceState
各個(gè)階段的回調(diào)逐工。
而每個(gè)階段分為三個(gè)小階段:
此階段之前膨疏、階段中、此階段之后
如對(duì)于Create階段钻弄,定義了三個(gè)回調(diào)方法:
#Application.java
public interface ActivityLifecycleCallbacks {
//Create階段之前
default void onActivityPreCreated(@android.annotation.NonNull Activity activity,
@android.annotation.Nullable Bundle savedInstanceState) {
}
//Create階段當(dāng)中
void onActivityCreated(@android.annotation.NonNull Activity activity, @android.annotation.Nullable Bundle savedInstanceState);
//Create階段之后
default void onActivityPostCreated(@android.annotation.NonNull Activity activity,
@android.annotation.Nullable Bundle savedInstanceState) {
}
//...
}
而只有處在當(dāng)前階段的方法必須要實(shí)現(xiàn)類實(shí)現(xiàn)佃却,其它兩個(gè)方法都是默認(rèn)的(default 修飾)。
生命周期回調(diào)原理
注冊(cè)了監(jiān)聽(tīng)后窘俺,來(lái)分析一下該回調(diào)是如何被調(diào)用的饲帅。
既然是監(jiān)聽(tīng)Activity 生命周期复凳,那么應(yīng)當(dāng)從Activity.java 里入手。
記得咱們之前分析的Activity 回調(diào)方法調(diào)用棧灶泵,還是以onCreate為例:
#Activity.java
protected void onCreate(@android.annotation.Nullable Bundle savedInstanceState) {
...
mFragments.dispatchCreate();
//分發(fā)
dispatchActivityCreated(savedInstanceState);
...
}
private void dispatchActivityCreated(@android.annotation.Nullable Bundle savedInstanceState) {
//調(diào)用Application里的方法
getApplication().dispatchActivityCreated(this, savedInstanceState);
}
而在Application.java里的實(shí)現(xiàn)為:
#Application.java
void dispatchActivityCreated(@android.annotation.NonNull Activity activity,
@android.annotation.Nullable Bundle savedInstanceState) {
//收集注冊(cè)列表育八,即是將mActivityLifecycleCallbacks(List),轉(zhuǎn)為數(shù)組
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
//調(diào)用對(duì)應(yīng)的回調(diào)方法
((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
savedInstanceState);
}
}
}
雖然以上只是分析了onCreate赦邻,然而其他方法也是同樣的套路髓棋,大同小異。
1惶洲、每當(dāng)Activity 處在不同的階段時(shí)按声,會(huì)檢測(cè)Application里是否有監(jiān)聽(tīng)它(Activity)的生命周期,若是則告知監(jiān)聽(tīng)者當(dāng)前所處的階段恬吕。
2签则、若是重寫了Activity 對(duì)應(yīng)的方法,并添加了打印铐料,那么Application里的回調(diào)方法先執(zhí)行才會(huì)執(zhí)行到Activity里的打印渐裂,因?yàn)樗窃贏ctivity父類里執(zhí)行的。
以上即是Activity 生命周期的梳理钠惩,下篇將會(huì)分析onSaveInstanceState/onRestoreInstanceState 原理以及應(yīng)用場(chǎng)景柒凉,并引入Jetpack ViewModel與之對(duì)比。
透明Activity/生命周期監(jiān)聽(tīng) demo 請(qǐng)查看:github合集
本文基于Android 10.0
您若喜歡篓跛,請(qǐng)點(diǎn)贊膝捞、關(guān)注,您的鼓勵(lì)是我前進(jìn)的動(dòng)力
持續(xù)更新中举塔,和我一起步步為營(yíng)系統(tǒng)绑警、深入學(xué)習(xí)Android
1、Android各種Context的前世今生
2央渣、Android DecorView 必知必會(huì)
3计盒、Window/WindowManager 不可不知之事
4、View Measure/Layout/Draw 真明白了
5芽丹、Android事件分發(fā)全套服務(wù)
6北启、Android invalidate/postInvalidate/requestLayout 徹底厘清
7、Android Window 如何確定大小/onMeasure()多次執(zhí)行原因
8拔第、Android事件驅(qū)動(dòng)Handler-Message-Looper解析
9咕村、Android 鍵盤一招搞定
10、Android 各種坐標(biāo)徹底明了
11蚊俺、Android Activity/Window/View 的background
12懈涛、Android Activity創(chuàng)建到View的顯示過(guò)
13、Android IPC 系列
14泳猬、Android 存儲(chǔ)系列
15批钠、Java 并發(fā)系列不再疑惑
16宇植、Java 線程池系列
17、Android Jetpack 前置基礎(chǔ)系列