Activity 之生命週期
本文內容:
1. Activity 介紹
2. Activity 的生命週期
2.1 生命週期圖
2.2 常見狀況下生命週期的回調
2.3 關於生命週期常見問題
2.4 異常狀態下活動的生命週期
2.4.1 資源配置改變致使 Activity 重建
2.4.2 低優先級 Activity 因爲內存不足被殺死
2.5 異常狀況下的處理
2.5.1 數據保存
2.5.2 防止重建
3. 關於 Activity 的不經常使用的回調方法
3.1 onPostCreate()
3.2 onPostResume()
3.3 onContentChanged()
3.4 onUserInteraction()
3.5 onUserLeaveHint()
1. Activity 介紹
Activity 是 Android 的四大組件之一,主要用於提供窗口與用戶進行交互。html
2. Activity 的生命週期
2.1 生命週期圖
官網的 Activity 的生命週期圖:
android
解釋圖中個方法的做用:web
生命週期方法 |
做用 |
說明 |
onCreate |
表示 Activity 正在被建立 |
activity 被建立時調用,通常在這個方法中進行活動的初始化工做,如設置佈局工做、加載數據、綁定控件等。 |
onRestart |
表示 Activity 正在從新啓動 |
這個回調錶明瞭 Activity 由徹底不可見從新變爲可見的過程,當 Activity 經歷了 onStop() 回調變爲徹底不可見後,若是用戶返回原 Activity,便會觸發該回調,而且緊接着會觸發 onStart() 來使活動從新可見。 |
onStart |
表示 Activity 正在被啓動 |
經歷該回調後,Activity 由不可見變爲可見,但此時處於後臺可見,還不能和用戶進行交互。 |
onResume |
表示 Activity 已經可見 |
已經可見的 Activity 從後臺來到前臺,能夠和用戶進行交互。 |
onPause |
表示 Activity 正在中止 |
當用戶啓動了新的 Activity ,原來的 Activity 再也不處於前臺,也沒法與用戶進行交互,而且緊接着就會調用 onStop() 方法,但若是用戶這時馬上按返回鍵回到原 Activity ,就會調用 onResume() 方法讓活動從新回到前臺。並且在官方文檔中給出了說明,不容許在 onPause() 方法中執行耗時操做,由於這會影響到新 Activity 的啓動。 |
onStop |
表示 Activity 即將中止 |
這個回調錶明瞭 Activity 由可見變爲徹底不可見,在這裏能夠進行一些稍微重量級的操做。須要注意的是,處於 onPause() 和 onStop() 回調後的 Activity 優先級很低,當有優先級更高的應用須要內存時,該應用就會被殺死,那麼當再次返回原 Activity 的時候,會從新調用 Activity 的onCreate()方法。 |
onDestroy |
表示 Activity 即將被銷燬 |
來到了這個回調,說明 Activity 即將被銷燬,應該將資源的回收和釋放工做在該方法中執行。 |
2.2 常見狀況下生命週期的回調
(A 與 B 表示不一樣的 Activity )框架
狀況 |
回調 |
第一次啓動 |
onCreate() -> onStart() -> onResume() |
從 A 跳轉到 B |
A_onPause() -> B_onCreate() -> B_onStart() -> B_onResume() -> A_onStop() |
從 B 再次回到 A |
B_onPause() -> A_onRestart() -> A_onStart() -> A_onResume() -> B_onStop() |
用戶按 home 鍵 |
onPause() -> onStop() |
按 home 鍵後回到應用 |
onRestart() -> onStart() -> onResume() |
用戶按電源鍵屏保 |
onPause() -> onStop() |
用戶按電源鍵亮屏 |
onRestart() -> onStart() -> onResume() |
用戶按 back 鍵回退 |
onPause() -> onStop() -> onDestroy() |
表中生命週期的驗證能夠在 Activity關於生命週期一些問題的實踐驗證 文章中查看。佈局
2.3 關於生命週期常見問題
問題 |
回調 |
由活動 A 啓動活動 B時,活動 A 的 onPause() 與 活動 B 的 onResume() 哪個先執行? |
活動 A 的 onPause() 先執行,活動 B 的 onResume() 方法後執行 |
標準 Dialog 是否會對生命週期產生影響 |
沒有影響 |
全屏 Dialog 是否會對生命週期產生影響 |
沒有影響 |
主題爲 Dialog 的 Activity 是否會對生命週期產生影響 |
有影響,與跳轉 Activity 同樣 |
關於生命週期的常見問題的驗證能夠在 Activity關於生命週期一些問題的實踐驗證 文章中查看。post
2.4 異常狀態下活動的生命週期
當 Activity 在運行過程當中發生一些狀況時,生命週期流程也會發生變化。常見的異常狀況有兩種,一種是資源配置改變;另外一是內存不足致使生命週期流程發生變化。字體
2.4.1 資源配置改變致使 Activity 重建
資源配置最多見的狀況就是橫豎屏切換致使資源的變化,當程序啓動時,會根據不一樣的配置加載不一樣的資源,例如橫豎屏兩個狀態對應着兩張不一樣的資源圖片。若是在使用過程當中屏幕忽然旋轉,那麼 Activity 就會由於系統配置發生改變而銷燬重建,加載合適的資源。ui
2.4.2 低優先級 Activity 因爲內存不足被殺死
後臺能夠同時運行多個任務,當設備的內存空間不足時,系統爲了保證用戶的體驗,會按照進程優先級將一些低優先級的進程殺死以會回收內存資源,後臺 Activity 就有可能會被銷燬。spa
系統回收進程的優先級:code
(1) 前臺進程
持有用戶正在交互的 Activty,即生命週期處於 onResume 狀態的活動。
該進程有綁定到正在交互的 Activity 的 service 或前臺 service。
(2) 可見進程
這種進程雖然不在前臺,可是仍然可見。
該進程持有的 Activity 執行了 onPause 但未執行 onStop 。例如原活動啓動了一個 dialog 主題的 Activity,但此時原活動並不是徹底不可見。
該進程有 service 綁定到可見的或前臺 Activity。
(3)服務進程
進程中持有一個 service,同時不屬於上面兩種狀況。
(4)後臺進程
不屬於上面三種狀況,但進程持有一個不可見的 Activity,即執行了 onStop 但未執行 onDestory 的狀態。
(5)空進程
不包含任何活躍的應用組件,做用是加快下次啓動這個進程中組件所須要的時間,優先級低。
2.5 異常狀況下的處理
在發生異常狀況後,用戶再次回到 Activity,原 Activity 會從新創建,原已有的數據就會丟失,好比用戶操做改變了一些屬性值,重建以後用戶就看不到以前操做的結果,在異常的狀況下如何給用戶帶來好的體驗,有兩種辦法。
2.5.1 數據保存
第一種就是系統提供的 onSaveInstanceState 和 onRestoreInstanceState 方法,onSaveInstanceState 方法會在 Activity 異常銷燬以前調用,用來保存須要保存的數據,onRestoreInstanceState 方法在 Activity 重建以後獲取保存的數據。
在活動異常銷燬以前,系統會調用 onSaveInstanceState,能夠在 Bundle 類型的參數中保存想要的信息,以後這個 Bundle 對象會做爲參數傳遞給 onRestoreInstanceState 和 onCreate 方法,這樣在從新建立時就能夠獲取數據了。
關於 onSaveInstanceState 與 onRestoreInstanceState 方法須要注意的一些問題:
1. onSaveInstanceState 方法的調用時機是在 onStop 以前,與 onPause 沒有固定的時序關係。而 onRestoreInstanceState 方法則是在 onStart 以後調用。
2. 正常狀況下的活動銷燬並不會調用這兩個方法,只有當活動異常銷燬而且有機會重現展現的時候纔會進行調用,除了資源配置的改變外,activity 因內存不足被銷燬也是經過這兩個方法保存數據。
3. 在 onRestoreInstanceState 和 onCreate 均可以進行數據恢復工做,可是根據官方文檔建議採用在 onRestoreInstanceState 中去恢復。
4. 在 onSaveInstanceState 和 onRestoreInstanceState 這兩個方法中,系統會默認爲咱們進行必定的恢復工做,具體地講,默認實現會爲佈局中的每一個 View 調用相應的 onSaveInstanceState() 方法,讓每一個視圖都能提供有關自身的應保存信息。Android 框架中幾乎每一個小部件都會根據須要實現此方法,以便在重建 Activity 時自動保存和恢復付 UI 所作的任何可見更改。例如 EditText 中的文本信息、ListView 中的滾動位置等。也能夠經過 android:saveEnabled 屬性設置爲 「false」 或經過調用 setSaveEnabled() 方法顯式阻止佈局內的視圖保存其狀態,一般不會將該屬性停用,除非想要以不一樣方式恢復 Activity IU 的狀態。
5. onSveInstanceState() 常見的觸發場景有:橫豎屏切換、按下電源鍵、按下菜單鍵、切換到別的 Activity 等;onRestoreInstanceState() 常見的觸發場景有:橫豎屏切換、切換語言等等。
2.5.2 防止重建
在默認狀況下,資源配置改變會致使活動的從新建立,可是能夠經過對活動的 android:configChanges 屬性的設置使活動防止從新被建立。
android:configChanges 屬性值
屬性值 |
含義 |
mcc |
SIM 卡惟一標識IMSI(國際移動用戶標識碼)中的國家代碼,由三位數字組成,中國爲:460,這裏標識 mcc 代碼發生了變化 |
mnc |
SIM 卡惟一標識 IMSI(國際移動用戶標識碼)中的運營商代碼,有兩位數字組成,中國移動 TD 系統爲 00 ,中國聯通爲 01,電信爲 03,此項標識 mnc 發生了改變 |
locale |
設備的本地位置發生了改變,通常指的是切換了系統語言 |
touchscreen |
觸摸屏發生了改變 |
keyboard |
鍵盤類型發生了改變,好比用戶使用了外接鍵盤 |
keyboardHidden |
鍵盤的可訪問性發生了改變,好比用戶調出了鍵盤 |
navigation |
系統導航方式發生了改變 |
screenLayout |
屏幕布局發生了改變,極可能是用戶激活了另一個顯示設備 |
fontScale |
系統字體縮放比例發生了改變,好比用戶選擇了個新的字號 |
uiMode |
用戶界面模式發生了改變,好比開啓夜間模式 -API8 新添加 |
orientation |
屏幕方向發生改變,好比旋轉了手機屏幕 |
screenSize |
當屏幕尺寸信息發生改變(當編譯選項中的 minSdkVersion 和 targeSdkVersion 均低於 13 時不會致使 Activity 重啓 ) API 13 新添加 |
smallestScreenSize |
設備的物理尺寸發生改變,這個和屏幕方向不要緊,好比切換到外部顯示設備 -API13 新添加 |
layoutDirection |
當佈局方向發生改變的時候,正常狀況下沒法修改佈局的 layoutDirection 的屬性 -API17 新添加 |
能夠在屬性中聲明多個配置值,方法使用 「|」 字符分割這些配置值。
API 級別 13 或更高版本的應用時,若要避免因爲設備方向改變(橫豎屏切換)而致使運行時重啓,則除了 「orientation」 值以外,還必須添加 「screenSize」 值。
當其中一個配置發生變化時,Activity 不會重啓。相反,Activity 會收到對 onConfigurationChanged() 的調用。向此方法傳遞 Configuration 對象指定新設備配置。能夠經過讀取 Configuration 中的字段,肯定新配置,而後經過更新界面中使用的資源進行適當的更改。
異常狀態下生命週期與異常狀況下的處理的的驗證能夠在 Activity關於生命週期一些問題的實踐驗證 文章中查看。
3 關於 Activity 的不經常使用的回調方法
3.1 onPostCreate()
onPostCreate() 方法是指 onCreate() 方法完全執行完畢的回調。通常咱們都沒有實現這個方法,它的做用是在代碼開始運行以前,調用系統作最後的初始化工做。如今知道的作法是使用 ActionBarDrawerToggle 時在屏幕旋轉的時候在 onPostCreate() 中同步下狀態。
3.2 onPostResume()
onPostResume() 與 onPostCreate() 方法相似,onPostResume() 方法在 onResume() 方法完全執行完畢的回調。 onCreate() 方法中獲取某個 View 的高度和寬度時,返回的值是 0 ,由於這個時候 View 可能還沒初始化好,可是在 onPostResume() 中獲取就不會有問題,由於 onPostResume() 是在 onResume() 完全執行完畢的回調。
3.3 onContentChanged()
當 Activity 的佈局改動時,即 setContentView() 或者 addContentView() 方法執行完畢時就會調用該方法。因此,Activity 中 View 的 findViewById() 方法均可以放到該方法中。
3.4 onUserInteraction()
Activity 不管分發按鍵事件、觸摸事件或者軌跡球事件都會調用 Activity#onUserInteraction()。若是想知道用戶用某種方式和你正在運行的 activity 交互,能夠重寫 Activity#onUserInteraction()。全部調用 Activity#onUserLeaveHint() 的回調都會首先回調 Activity#onUserInteraction() 。
Activity 在分發各類事件的時候會調用該方法,注意:啓動另外一個 activity ,Activity#onUserInteraction()會被調用兩次,一次是 activity 捕獲到事件,另外一次是調用 Activity#onUserLeaveHint() 以前會調用 Activity#onUserInteraction() 。
能夠用這個方法來監控用戶有沒有與當前的 Activity 進行交互。
3.5 onUserLeaveHint()
當用戶的操做使一個 activity 準備進入後臺時,此方法會像 activity 的生命週期的一部分被調用。例如,當用戶按下 Home 鍵,Activity#onUserLeaveHint() 將會被調用。可是當來電致使 activity 自動佔據前臺(系統自動切換),Activity#onUserLeaveHint() 將不會被回調。
通常監聽返回鍵,是重寫 onKeyDown() 方法,可是 Home 鍵和 Menu 鍵就很差監聽,可是能夠在 onUserLeaveHint() 方法中監聽。
參考文章:
- 老生常談-Activity
- 全面瞭解 Activity
- 超詳細的生命週期圖-你能回答全嗎
- Android之Activity系列總結(一)—Activity概覽