Android 四大組件 —— Activity
Actvity是Android中的四大組件之一,平常我們?cè)谑謾C(jī)一個(gè)用程序上所看的界面就是 Activity 的表現(xiàn)形式。而且 Activity 也是用戶唯一能夠感知到的組件,每一個(gè)UI的界面就是通過 Activity 顯示在屏幕上的,平常我們?cè)谲浖镞M(jìn)行的各種頁面的切換很大一部分是不同 Activity 的跳轉(zhuǎn)。
我們?cè)谌粘I钪胁豢杀苊獾拇蜷_很多個(gè)不同的應(yīng)用, Activity 的生命周期便是從我們點(diǎn)開圖標(biāo)的那一瞬間開始的。,Google官方給出了Activity的生命周期圖,如下:

先來看看它的幾個(gè)回調(diào)方法:
onCreate():此方法在活動(dòng)創(chuàng)建時(shí)被觸發(fā),此時(shí)活動(dòng)處于創(chuàng)建狀態(tài),一般 Activity 的一些初始化的工作在該方法中執(zhí)行,且在生命周期內(nèi)只會(huì)執(zhí)行一次。在該方法調(diào)用 setContentView 中進(jìn)行 View 的創(chuàng)建。
onStart():這個(gè)方法緊接著 onCreate ,此時(shí)已經(jīng)是可以看到活動(dòng)的了,但是無法進(jìn)行交互。此時(shí) Activity 處于啟動(dòng)的狀態(tài)。緊接著會(huì)回調(diào) onResume() 。
onResume():此時(shí) Activity 處于 Resume 狀態(tài),位于前臺(tái)完全可見也可以進(jìn)行交互,我們看到的界面便是 Activity 保持在 onResume() 狀態(tài)。該方法之后是 onPause() 方法。
onPause():該方法是在 onResume 之后執(zhí)行的,此時(shí)活動(dòng)處于暫停狀態(tài),不在位于前臺(tái),可見但是無法交互。這個(gè)方法的執(zhí)行時(shí)間非常短,因此不應(yīng)該在此方法中執(zhí)行重量級(jí)的資源釋放。
onStop():此時(shí)活動(dòng)對(duì)用戶已經(jīng)不可見了。緊接著會(huì)回調(diào) onRestart() 或者 onDestory()。此時(shí) Activity 處于 Stopped 狀態(tài),活動(dòng)的控件實(shí)例還是存在的,只是沒有被顯示。此方法中可以釋放對(duì)用戶不可見時(shí)的資源。也可以在此方法中進(jìn)行數(shù)據(jù)的保存。
onRestart():表示 Activity 從停止?fàn)顟B(tài)重新啟動(dòng)。后面會(huì)回調(diào) onStart()
onDestroy():活動(dòng)被銷毀,這是系統(tǒng)生命周期的最后一個(gè)回調(diào)。一般在這個(gè)回調(diào)中進(jìn)行釋放所有還未釋放的資源。
用戶打開和關(guān)閉應(yīng)用程序的過程其實(shí)就是 Activity 在不同的狀態(tài)之間進(jìn)行切換的過程。我們所做的就是在正確的狀態(tài)下執(zhí)行需要的邏輯。
Activity 的生命周期分為兩種情況:一種是正常情況下,一種是異常情況下。
- 正常情況下就是用戶正常打開應(yīng)用,是用完之后按返回鍵退出,以上的回調(diào)方法執(zhí)行順序如下:
onCreate -> onStart -> onResume -> 用戶操作 -> onPause -> onStop -> onDestory
-
當(dāng)應(yīng)用在啟動(dòng)或者用戶使用的過程中發(fā)生了什么意外,就是異常情況下的生命周期,異常情況下的生命周期要分情況討論:
系統(tǒng)配置發(fā)生改變:比如屏幕的方向發(fā)生旋轉(zhuǎn)、該改變語言環(huán)境,或者輸入設(shè)備發(fā)生更改。當(dāng)這些發(fā)生時(shí), Activity 會(huì)被銷毀和重建, Activity 會(huì)執(zhí)行
onPause -> onStop -> onDestory -> onCreate -> onStart -> onResume手機(jī)變?yōu)槎啻翱冢篈ndroid 7.0 以后,增加了一個(gè)“多窗口”模式,應(yīng)用程序進(jìn)入多窗口模式或者在多窗口模式中改變大小都會(huì)引發(fā)系統(tǒng)配置的更改,可以在代碼中自行處理配置更改,也可以對(duì) Activity 進(jìn)行銷毀和重建
當(dāng)前的 Actiivty 被新的 Activity 或者 Dialog 所部分覆蓋。這種情況下當(dāng)前的 Activity 會(huì)回調(diào) onPause 方法。當(dāng)新的 Activity 退出或者 Dialog 消失使會(huì)重新調(diào)用 onResume 方法。如果完全覆蓋則會(huì)調(diào)用 onStop 方法,再回到該界面時(shí)則會(huì)回調(diào) onStart 。
系統(tǒng)的內(nèi)存不足時(shí),會(huì)殺死后臺(tái)的進(jìn)程來確保前臺(tái)應(yīng)用的正常運(yùn)行。
關(guān)于系統(tǒng)配置改變時(shí) Activity 重建的情況,Android 提供了一個(gè)屬性用于在指定屬性發(fā)生改變時(shí)不重建 Activity,該屬性為: android:configChanges ,不同的值用“|”連接。該屬性的值如下:
mcc:SIM卡唯一標(biāo)識(shí)IMSI(國際移動(dòng)用戶識(shí)別碼)中的代碼,有三位數(shù)組成,中國為460,此項(xiàng)標(biāo)識(shí)mcc代碼發(fā)生了改變
mnc:SIM卡唯一標(biāo)識(shí)了IMSI(國際移動(dòng)用戶識(shí)別碼)中的運(yùn)營商代碼,由兩位數(shù)組成,中國移動(dòng)TD系統(tǒng)為00,中國聯(lián)通為01,中國電信為03,此項(xiàng)標(biāo)識(shí)mnc發(fā)生了改變
locale:設(shè)備本地位置發(fā)生了改變,一般指切換了系統(tǒng)語言
touchscreen:觸摸屏發(fā)生了改變,這個(gè)很費(fèi)解,正常情況下無法發(fā)生,可以忽略它
keyboard:鍵盤類型發(fā)生了改變,比如用戶使用了外插鍵盤
keyboardHidden:鍵盤的可問性發(fā)生了改變,比如用戶調(diào)出了鍵盤
navigation:系統(tǒng)導(dǎo)航方式發(fā)生了改變,比如采用了軌跡球?qū)Ш?,這個(gè)很難發(fā)生,可以忽略它
screenLayout:屏幕布局發(fā)生了改變,很可能是用戶激活了另一個(gè)顯示設(shè)備
fontStyle:系統(tǒng)的字體縮放比例發(fā)生了改變,比如用于選擇了一個(gè)新的字號(hào)
uiMode:用戶界面模式發(fā)生了改變,比如是否開啟了夜間模式(API 8添加)
orientation:屏幕方向發(fā)生了改變,這個(gè)是最常用的,比如旋轉(zhuǎn)了手機(jī)屏幕
screenSize:當(dāng)屏幕的尺寸信息發(fā)生了改變,當(dāng)旋轉(zhuǎn)設(shè)備屏幕時(shí),屏幕尺寸會(huì)發(fā)生變化,這個(gè)選項(xiàng)比較特殊,它和編譯選項(xiàng)有關(guān),當(dāng)編譯選項(xiàng)中的minSdkVersion和targetSdkVersion均低于13時(shí),此選項(xiàng)不會(huì)導(dǎo)致Activity重啟,否則會(huì)導(dǎo)致Activity重啟(API 13重新添加)
smallestScreenSize:設(shè)備的物理尺寸發(fā)生了改變,這個(gè)項(xiàng)目和屏幕的方向沒有關(guān)系,僅僅在實(shí)際的物理屏幕尺寸改變時(shí)的時(shí)候發(fā)生,比如用戶切換到了外部的顯示設(shè)備,這個(gè)選項(xiàng)和screenSize一樣,這個(gè)選項(xiàng)不會(huì)導(dǎo)致Activity重啟否則會(huì)導(dǎo)致Activity重啟
layoutDirection:當(dāng)布局發(fā)現(xiàn)發(fā)生變化,這個(gè)屬性用的比較少,正常情況下無需修改布局的layoutDirection屬性(API 17時(shí)添加)
我們常用的只有 locale 、orientation 和 keyboardHidden 這三個(gè)選項(xiàng)。當(dāng)系統(tǒng)配置發(fā)生改變時(shí),系統(tǒng)會(huì)回調(diào)onConfigurationChanged方法。另外,Android 3.2 之后,當(dāng)設(shè)備的方向發(fā)生改變時(shí),同時(shí)也會(huì)觸發(fā)屏幕的尺寸信息改變,因此 “orientation” 要與 “screenSize” 一起使用才會(huì)生效
關(guān)于系統(tǒng)進(jìn)程的優(yōu)先級(jí),Android 根據(jù)進(jìn)程中運(yùn)行的組件以及其所處的狀態(tài)對(duì)進(jìn)程做了一個(gè)優(yōu)先級(jí)的劃分(從高到低):
-
前臺(tái)進(jìn)程:用戶當(dāng)前正在使用的進(jìn)程。一個(gè)前臺(tái)進(jìn)程需要具備以下條件的任意一個(gè)或者幾個(gè):
有一個(gè)顯示在當(dāng)前用戶屏幕的最上面的 Activity ,并且正在與用戶進(jìn)行交互(此時(shí) onResume 已經(jīng)被調(diào)用了)
進(jìn)程中的有一個(gè)廣播接收器正在執(zhí)行 onReceive 方法。
進(jìn)程中有一個(gè)服務(wù)正在執(zhí)行它的某一個(gè)回調(diào)( onCreate, onStart() 或者 onDestory())
-
可見進(jìn)程:正在執(zhí)行用戶感知得到的任務(wù)。它需要具備以下條件的一個(gè)或幾個(gè):
該進(jìn)程中運(yùn)行的一個(gè) Activity 對(duì)用戶可見但不處于交互狀態(tài)。例如 Activity 被部分覆蓋的情況
該進(jìn)程中有一個(gè)運(yùn)行在前臺(tái)的服務(wù)(正在執(zhí)行 Service.startForeground() 方法。)
承載一個(gè)用于執(zhí)行特定功能的系統(tǒng)服務(wù),比如動(dòng)態(tài)壁紙,輸入法等等,這些服務(wù)是能夠被用戶感知的。
服務(wù)進(jìn)程:該進(jìn)程包含一個(gè)已啟動(dòng)的后臺(tái)服務(wù),這些服務(wù)一般在后臺(tái)執(zhí)行一些用戶所關(guān)心的任務(wù)(比如網(wǎng)絡(luò)數(shù)據(jù)的上傳和下載)。在 Android 會(huì)對(duì)運(yùn)行時(shí)間過長的服務(wù)進(jìn)行降級(jí)以避免服務(wù)長時(shí)間運(yùn)行而導(dǎo)致內(nèi)存泄漏或者內(nèi)存被大量占用。
緩存進(jìn)程:該進(jìn)程在系統(tǒng)中是可有可無的,因此在系統(tǒng)需要內(nèi)存的時(shí)候會(huì)殺死。這些進(jìn)程一般包含大量對(duì)用戶不可見的 Activity 。系統(tǒng)有一個(gè)列表用于保存這些緩存進(jìn)程,該列表中的最后一個(gè)進(jìn)程是最先被系統(tǒng)回收的進(jìn)程。
注:進(jìn)程之間的依賴性對(duì)進(jìn)程的優(yōu)先級(jí)也會(huì)有影響。比如進(jìn)程 A 綁定到帶有 Context.bind_auto_create標(biāo)志的服務(wù),那么該服務(wù)所在的進(jìn)程的優(yōu)先級(jí)至少是和 A 進(jìn)程的優(yōu)先級(jí)一樣。
參考:
《Android 開發(fā)藝術(shù)探索》第一章