Activity 生命周期
onCreate —— onStart 可見 —— onResume 有焦點 —— onPause 無焦點 —— onStop 不可見 —— onDestory
- onRestart 由不可見重新回到前臺時調(diào)用
- 所有生命周期方法重寫實現(xiàn)必須調(diào)用其父類方法
- 由于 Activity 經(jīng)常在暫停和恢復之間來回切換眼俊,所以 onResume 和 onPause 的邏輯應該是輕量級的
- 圖中顯示系統(tǒng)在某些情況下回收內(nèi)存導致 onStop,onDestory 可能不被調(diào)用店印,因此可以根據(jù)實際情況在 onPause 中保存一些重要數(shù)據(jù),耗時操作需要開子線程處理
經(jīng)典場景
場景 1 第一次啟動 Activity A
//Activity A
onCreate -> onStart -> onResume
場景 2 在 Activity A 上啟動 Activity B
//Activity A
onPause ->(Activity A 被 Activity B 覆蓋后走)onStop ->(如果 Activity A 自身 finish 或是被系統(tǒng)回收后走)onDestory
//Activity B
onCreate -> onStart ->(Activity B 會等到 Activity A 的 onPause 執(zhí)行后走)onResume
- 如果 Activity B 是完全透明或?qū)υ捒蛑黝}的 ,那么 Activity A 就不繼續(xù)走 onStop
- onPause 不能進行耗時操作
場景 3 從 Activity B 返回到 Activity A
//Activity B
onPause -> onStop -> onDestory
//Activity A
onRestart -> onStart -> onResume
//如果 Activity A 自身 finish 或是被系統(tǒng)回收后,則這么走
onCreate (重新創(chuàng)建) -> onStart -> onResume
場景 4 鎖屏與解鎖
//鎖屏
onPause,不會走 onStop
//解鎖
onResume
場景 5 點擊 HOME 鍵吹零、來電
//點擊 Home 鍵、來電
onPause -> onStop
//回到 App
onRestart -> onStart -> onResume
//前臺 Activity finish 了或被系統(tǒng)回收了从铲,則這么走
onCreate (重新創(chuàng)建) -> onStart -> onResume
生命周期該做的事
onCreate
- 調(diào)用 setContentView 方法設置布局
- 定義成員變量瘪校,初始化數(shù)據(jù)
- 初始化視圖澄暮、控件名段、UI 元素
- 配置 UI,將數(shù)據(jù)綁定到列表等
- 將 Activity 與 ViewModel 相關聯(lián)
應盡量減少 onCreate 的工作量泣懊,避免程序啟動太久而看不見界面伸辟,可以通過 savedInstanceState 參數(shù)恢復一些狀態(tài),如果是第一次創(chuàng)建則為 null 需要做判空處理
onStart
- 如注冊一個監(jiān)聽 UI 變化的廣播
- 把在 onStop 中釋放的資源重新創(chuàng)建回來
onResume
- 把 onPause 中停止的操作恢復回來馍刮,如 Camera 預覽
- 開始動畫
意味著此時 Activity 位于 Activity 堆棧的頂部信夫,獲取了焦點
onPause
- 釋放系統(tǒng)資源,傳感器(例如 GPS)手柄卡啰、Camera 等
- 停止動畫
不應該在這里保存應用或用戶數(shù)據(jù)静稻、進行網(wǎng)絡調(diào)用或執(zhí)行數(shù)據(jù)庫事務,即不適合做耗時較長的工作
地圖導航頁面一般不在這里釋放匈辱,因為希望它仍然能夠繼續(xù)工作
應最大程度減少 onPause 的工作量避免 Activity 切換緩慢卡頓
onStop
應該釋放那些不再需要的資源
按需從精確位置更新切換到粗略位置更新
關閉那些 CPU 執(zhí)行相對密集的操作
將用戶內(nèi)容(如郵箱草稿)保存到持久性存儲空間
用戶首選項持久性數(shù)據(jù)或數(shù)據(jù)庫中的數(shù)據(jù)
停止通過 Service 定時更新 UI 上的數(shù)據(jù)的 Service
可以在這里保存應用或用戶數(shù)據(jù)振湾、進行網(wǎng)絡調(diào)用或執(zhí)行數(shù)據(jù)庫事務
onDestoty
- 應釋放先前的回調(diào)(如 onStop )尚未釋放的所有資源
不推薦在 onDestroy 里執(zhí)行釋放資源的工作,因為 onDestroy 執(zhí)行的時機可能較晚亡脸,可根據(jù)實際需求在
onPause 或 onStop 中結(jié)合 isFinishing 判斷來執(zhí)行
異常情況下的生命周期
- 內(nèi)存不足后導致 Activity 被系統(tǒng)回收押搪,系統(tǒng)不會直接終止 Activity 以釋放內(nèi)存,而是會終止 Activity 所在的進程浅碾,系統(tǒng)不僅會銷毀 Activity大州,還會銷毀在該進程中運行的所有其他內(nèi)容
- Configuration 配置發(fā)生了改變:橫豎屏切換、系統(tǒng)語言改變垂谢、輸入設備的改變厦画、切換到多窗口模式( Android 7.0 Api 24 )
- 使用【設置】里的【應用管理器】來停止應用以終止進程
Activity 會先銷毀再重建
onSaveInstanceState
super.onSaveInstanceState 里已經(jīng)實現(xiàn)保存視圖層次結(jié)構(gòu)的狀態(tài)的邏輯
保存有關 Activity 的 view hierarchy state 視圖層次結(jié)構(gòu)狀態(tài)的瞬時信息(如輸入框的值、列表滑動后停留的位置)滥朱,系統(tǒng)用于恢復先前狀態(tài)的已保存數(shù)據(jù)稱為實例狀態(tài)苛白,是存儲在 Bundle 對象中的鍵值對集合,默認情況下焚虱,系統(tǒng)使用 Bundle 實例狀態(tài)來保存 Activity 布局中每個 View 對象的相關信息购裙,系統(tǒng)因系統(tǒng)限制(例如配置變更或內(nèi)存壓力)而銷毀 Activity 時候,如果用戶嘗試回退到該 Activity鹃栽,系統(tǒng)將使用一組描述 Activity 銷毀時狀態(tài)的已保存數(shù)據(jù)新建該 Activity 的實例躏率,無需編寫代碼就能恢復布局狀態(tài)為其先前的狀態(tài)躯畴,
Bundle 對象并不適合保留大量數(shù)據(jù),在主線程中進行序列化和反序列化薇芝,會產(chǎn)生一定內(nèi)存消耗
保存臨時數(shù)據(jù)為主蓬抄,保存簡單輕量的界面狀態(tài),如果保存大量數(shù)據(jù)應該配合使用 ViewModel 進行處理
調(diào)用在 onStop 之前
主動調(diào)用 finish 方法和點擊返回鍵的時候是不會調(diào)用該方法保存狀態(tài)的
onRestoreInstanceState
super.onRestoreInstanceState 已經(jīng)實現(xiàn)恢復視圖層次結(jié)構(gòu)的狀態(tài)的邏輯
調(diào)用在 onStart 之后
可用于恢復一些 onSaveInstanceState 方法中保存的數(shù)據(jù)
橫豎屏切換
不設置 Activity 的 android:configChanges 時夯到,切屏會重新調(diào)用各個生命周期嚷缭,切橫屏時會執(zhí)行一次,切豎屏時會執(zhí)行兩次
設置 Activity 的 android:configChanges="orientation" 時耍贾,切屏還是會重新調(diào)用各個生命周期阅爽,切橫、豎屏時只會執(zhí)行一次
設置 Activity 的 android:configChanges="orientation|keyboardHidden" 時荐开,切屏不會重新調(diào)用各個生命周期付翁,只會執(zhí)行 onConfigurationChanged 方法
常見問題
1 如果在 onCreate 方法中直接調(diào)用 finish 方法,生命周期是怎樣的晃听?
系統(tǒng)會跳過其他生命周期直接調(diào)用 onDestory 方法百侧,其實在任何一個生命周期調(diào)用 finish 方法都會跳過這之前的所有其他生命周期
2 什么時候只會走 onPause,而不會走 onStop 能扒?
- 鎖屏
- 打開一個完全透明或?qū)υ捒蛑黝}的 Activity
3 Activity 在什么時候會出現(xiàn)不執(zhí)行 onDestory 的情況佣渴?
主線程異常崩潰
應用被強殺
4 下拉狀態(tài)欄時 Activity 的生命周期是什么?
不走任何生命周期初斑,狀態(tài)欄和 AlertDialog辛润、Toast 等都是通過 WindowManager.addView 方法來顯示的,對 Activity 的生命周期沒有影響越平,另外可以通過 onWindowFocusChanged(boolean hasFocus) 監(jiān)聽狀態(tài)欄频蛔,hasFocus 為 false 可以表示下拉狀態(tài),從而可以實現(xiàn)暫停視頻等需求
5 啟動一個其它應用的 Activity 的生命周期分析秦叛?
6 如何統(tǒng)計 Activity 的工作時間晦溪?