Activity 生命周期

Android Activity 生命周期

官方文檔 https://developer.android.google.cn/guide/components/activities/activity-lifecycle

核心回調(diào)

  • 6 個(gè)核心的生命周期
onCreate —— onStart 可見(jiàn) —— onResume 有焦點(diǎn) —— onPause 無(wú)焦點(diǎn) —— onStop 不可見(jiàn) —— onDestory
  • onRestart 回調(diào)方法是在 Activity 從不可見(jiàn)(onStop)重新回到前臺(tái)時(shí)調(diào)用的
  • 所有生命周期回調(diào)方法重寫(xiě)時(shí)必須調(diào)用其父類(lèi)方法
  • 由于 Activity 經(jīng)常在暫停和恢復(fù)之間來(lái)回切換,所以 onResume 和 onPause 的邏輯應(yīng)該是輕量級(jí)的
  • 圖中顯示系統(tǒng)在某些情況下回收內(nèi)存導(dǎo)致 onStop 和 onDestory 可能不被調(diào)用,因此可以根據(jù)實(shí)際情況在 onPause 中保存一些非常重要的數(shù)據(jù),耗時(shí)操作需要開(kāi)子線程處理

經(jīng)典場(chǎng)景

  • 1 第一次啟動(dòng) Activity A
//Activity A
onCreate -> onStart -> onResume
  • 2 在 Activity A 上啟動(dòng) Activity B
//Activity A,如果 Activity B 是完全透明或是對(duì)話框主題的話,那么 A 就不繼續(xù)走 onStop 了
onPause ->(A 被 B 覆蓋不可見(jiàn)后走)onStop ->(如果 A 自身 finish 或被系統(tǒng)回收后走)onDestory
//Activity B
onCreate -> onStart ->(B 會(huì)等到 A 的 onPause 執(zhí)行后走)onResume
  • 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 點(diǎn)擊 HOME 鍵、來(lái)電
//點(diǎn)擊 Home 鍵、來(lái)電
onPause -> onStop 
//回到 App
onRestart -> onStart -> onResume  
//如果被系統(tǒng)回收了,則這么走
onCreate(重新創(chuàng)建) -> onStart -> onResume
  • 5 鎖屏與解鎖
//鎖屏
onPause -> onStop
//解鎖
onRestart -> onStart -> onResume
//如果被系統(tǒng)回收了,則這么走
onCreate(重新創(chuàng)建) -> onStart -> onResume

生命周期推薦做的事

onCreate

  • 應(yīng)該盡量減少 onCreate 的工作量,避免程序啟動(dòng)太久而看不見(jiàn)界面,這里可以通過(guò) savedInstanceState 參數(shù)恢復(fù)一些狀態(tài),如果 Activity 是第一次創(chuàng)建的話此時(shí) savedInstanceState 為 null ,所以需要做判空處理
  • 應(yīng)該調(diào)用 setContentView 方法初始化布局
  • 定義成員變量(全局變量),初始化相關(guān)數(shù)據(jù)
  • 初始化視圖控件等 UI 元素、配置 UI,將數(shù)據(jù)綁定到列表等
  • 可能需要將 Activity 與 ViewModel 相關(guān)聯(lián)
  • 可能需要啟動(dòng)與 Service 服務(wù)的綁定操作

onStart

  • 注冊(cè) BroadcastReceiver 廣播接收器
  • 地圖導(dǎo)航位置更新等相關(guān)的初始化
  • 把在 onStop 中釋放的資源重新創(chuàng)建回來(lái)

onResume

  • 意味著此時(shí) Activity 位于 Activity 堆棧的頂部,獲取了焦點(diǎn)
  • 把 onPause 中暫停的操作恢復(fù)回來(lái),如 Camera 預(yù)覽
  • 開(kāi)始動(dòng)畫(huà)、視頻的播放
  • 可能需要注冊(cè)傳感器(如 GPS)監(jiān)聽(tīng)

onPause

  • 不推薦在這里保存應(yīng)用或用戶數(shù)據(jù)、進(jìn)行網(wǎng)絡(luò)請(qǐng)求調(diào)用或執(zhí)行數(shù)據(jù)庫(kù)事務(wù)(可根據(jù)實(shí)際情況在 onPause 中保存一些非常重要的數(shù)據(jù)),即不適合做耗時(shí)較長(zhǎng)的工作,應(yīng)最大程度減少 onPause 的工作量避免 Activity 切換緩慢卡頓
  • 釋放系統(tǒng)資源,傳感器(如 GPS)句柄、Camera 預(yù)覽等,通常是耗電的
  • 停止動(dòng)畫(huà)、視頻的播放
  • 地圖導(dǎo)航頁(yè)面一般不在這里釋放,因?yàn)橄M匀荒軌蚶^續(xù)工作

onStop

  • 可以在這里保存應(yīng)用或用戶數(shù)據(jù)(比如將用戶編寫(xiě)的郵箱草稿保存到持久性存儲(chǔ)空間)、進(jìn)行網(wǎng)絡(luò)調(diào)用、用戶首選項(xiàng)持久性數(shù)據(jù)和執(zhí)行數(shù)據(jù)庫(kù)事務(wù)
  • 應(yīng)該釋放那些不再需要的資源
  • 關(guān)閉那些 CPU 執(zhí)行相對(duì)密集的操作
  • 地圖導(dǎo)航可根據(jù)實(shí)際情況按需從精確位置更新切換到粗略位置更新
  • 可以停止通過(guò) Service 定時(shí)更新 UI 上的數(shù)據(jù)的 Service
  • 取消注冊(cè) BroadcastReceiver 廣播接收器

onDestoty

  • 應(yīng)釋放先前的回調(diào)(如 onStop)中尚未釋放的所有資源
  • 解除與 Service 服務(wù)的綁定
  • 其實(shí)不推薦在 onDestroy 里執(zhí)行銷(xiāo)毀資源的工作,因?yàn)?onDestroy 執(zhí)行的時(shí)機(jī)可能較晚,可根據(jù)實(shí)際需求在
    onPause 或 onStop 中結(jié)合 isFinishing 判斷來(lái)執(zhí)行

特殊情況下的生命周期

  • 1 系統(tǒng)資源不足的情況下導(dǎo)致 Activity 被系統(tǒng)回收
  • 2 系統(tǒng) Configuration 配置改變:橫豎屏切換、系統(tǒng)語(yǔ)言改變和切換到多窗口或分屏模式等
  • 3 用戶強(qiáng)殺應(yīng)用或者使用系統(tǒng)【設(shè)置】里的【應(yīng)用管理器】來(lái)停止應(yīng)用以終止進(jìn)程
  • 4 應(yīng)用程序出現(xiàn)異常崩潰

onSaveInstanceState

  • 在 Activity 被系統(tǒng)銷(xiāo)毀并重新創(chuàng)建后調(diào)用,通常會(huì)在 onStop 之前調(diào)用
  • Instance State 實(shí)例狀態(tài),是一個(gè)鍵值對(duì)集合存儲(chǔ)在 Bundle 對(duì)象中,保存著有關(guān) Activity 的 View Hierarchy State 視圖層次結(jié)構(gòu)狀態(tài)的瞬時(shí)信息(如輸入框的值、列表滑動(dòng)后停留的位置),系統(tǒng)用它來(lái)恢復(fù) Activity 先前的狀態(tài),默認(rèn)情況下系統(tǒng)使用 Bundle 對(duì)象中的實(shí)例狀態(tài)來(lái)保存 Activity 布局中每個(gè) View 對(duì)象的相關(guān)信息,系統(tǒng)因系統(tǒng)限制(例如 Configuration 配置變更或內(nèi)存壓力)等情況而銷(xiāo)毀 Activity 的場(chǎng)景,當(dāng)用戶嘗試回退到該 Activity 時(shí),系統(tǒng)會(huì)通過(guò)已保存的實(shí)例狀態(tài)去新建該 Activity 的實(shí)例,也就是整個(gè)過(guò)程 Activity 會(huì)先銷(xiāo)毀再重建,即無(wú)需編寫(xiě)代碼就能恢復(fù)布局狀態(tài)為其先前的狀態(tài),主動(dòng)調(diào)用 finish 方法和點(diǎn)擊返回鍵的場(chǎng)景是不會(huì)調(diào)用該方法保存狀態(tài)的
  • super.onSaveInstanceState 里默認(rèn)已經(jīng)實(shí)現(xiàn)保存視圖層次結(jié)構(gòu)狀態(tài)的邏輯
  • Bundle 對(duì)象并不適合保留大量數(shù)據(jù),在主線程中進(jìn)行序列化和反序列化,會(huì)產(chǎn)生一定內(nèi)存消耗,保存臨時(shí)數(shù)據(jù)為主,保存簡(jiǎn)單輕量的界面狀態(tài),如果保存大量數(shù)據(jù)應(yīng)該配合使用 ViewModel 進(jìn)行處理

onRestoreInstanceState

  • 在 Activity 被系統(tǒng)銷(xiāo)毀并重新創(chuàng)建后調(diào)用,用于恢復(fù)之前保存的狀態(tài)數(shù)據(jù),通常在 onStart 或 onResume 之后調(diào)用
  • 可用于恢復(fù)一些 onSaveInstanceState 方法中保存的數(shù)據(jù)
  • super.onRestoreInstanceState 已經(jīng)實(shí)現(xiàn)恢復(fù)視圖層次結(jié)構(gòu)的狀態(tài)的邏輯

橫豎屏切換

  • 如果是重建 Activity 的情況下,需要利用 onSaveInstanceState 和 onRestoreInstanceState 方法處理數(shù)據(jù)的保存與恢復(fù),來(lái)保證用戶數(shù)據(jù)或狀態(tài)不丟失
  • 如果是不重建 Activity 情況下,那么我們可以按需利用 onConfigurationChanged 回調(diào)進(jìn)行判斷來(lái)展示橫豎屏不同界面的展示
//Android 3.2 API 13 以前
不設(shè)置 Activity 的 android:configChanges 時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次
設(shè)置了 Activity 的 android:configChanges="orientation" 時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r都只會(huì)執(zhí)行一次
設(shè)置了 Activity 的 android:configChanges="orientation|keyboardHidden" 時(shí),切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行 onConfigurationChanged 方法

//Android 3.2 API 13 及以后
不設(shè)置 Activity 的 android:configChanges 時(shí),或者設(shè)置了 Activity 的 android:configChanges="orientation" 時(shí),或者設(shè)置了 Activity 的android:configChanges="orientation|keyboardHidden" 時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行一次
設(shè)置了 Activity 的 android:configChanges="orientation|screenSize|keyboardHidden",切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行 onConfigurationChanged 方法

常見(jiàn)問(wèn)題

1 如果在 onCreate 、onStart 和 onResume 等方法中直接調(diào)用 finish 方法,生命周期是怎樣的?

  • 系統(tǒng)會(huì)跳過(guò)對(duì)應(yīng)的生命周期方法,可以簡(jiǎn)單理解 onCreate 和 onDestory ,onStart 和 onStop ,onResume 和 onPause 是對(duì)應(yīng)的,原理可以參見(jiàn)源碼里 Instrumentation 的判斷邏輯
//調(diào)用 finish 方法的時(shí)機(jī)
onCreate:onCreate -> onDestroy
onStart :onCreate -> onStart -> onStop -> onDestroy
onResume:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy

2 什么時(shí)候只會(huì)走 onPause 方法,而不會(huì)走 onStop 方法?

  • 打開(kāi)一個(gè)完全透明或是對(duì)話框主題的 Activity 的情況

3 Activity 在什么時(shí)候可能會(huì)出現(xiàn)不執(zhí)行 onDestory 方法的情況?

  • 系統(tǒng)資源不足的情況下
  • 用戶強(qiáng)殺應(yīng)用或者使用系統(tǒng)【設(shè)置】里的【應(yīng)用管理器】來(lái)停止應(yīng)用以終止進(jìn)程
  • 應(yīng)用程序異常崩潰
  • 切到多窗口或分屏模式

4 下拉狀態(tài)欄時(shí) Activity 的生命周期是什么?

  • 不走任何生命周期,狀態(tài)欄和 AlertDialog、Toast 等都是通過(guò) WindowManager.addView 方法來(lái)顯示的,對(duì) Activity 的生命周期沒(méi)有影響,另外可以通過(guò) onWindowFocusChanged(boolean hasFocus) 來(lái)監(jiān)聽(tīng)狀態(tài)欄,hasFocus 為 false 可以表示下拉狀態(tài),從而可以實(shí)現(xiàn)暫停視頻等需求
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容