Android 深刻理解Activity生命週期的作用及意義
前言
Activity生命週期是研究Android開發最基礎的知識點之一,熟練掌握生命週期的特性可以在實際開發中避免踩坑。比如,一些UI的初始化和回收操作、框架庫的註冊於反註冊(摧毀)、執行緒的啟動和停止等。另外,本文在最後章節還會講解系統回收造成的問題。本文就是針對各生命週期進行分析和解答,幫助大家完全掌握生命週期。
推薦閱讀:
一、基本作用
Activity的生命週期共七個指示器:onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart。
如下圖所示。
(1)onCreate() ,不可見狀態
在Activity被建立時回撥,第一個生命週期。
(2)onStart() ,可見狀態
該方法回調錶示Activity正在啟動,此時Activity處於可見狀態,只是還沒有在前臺顯示,因此使用者也無法互動。可以簡單理解為Activity已顯示卻無法被使用者看見。
(3)onResume() ,可見狀態
此方法回撥時,Activity已在在螢幕上顯示UI並允許使用者操作了。從流程圖可見,當Activity停止後(onPause、onStop方法被呼叫),重新回到前臺時也會呼叫onResume方法。可以在onResume方法中初始化一些資源,比如開啟相機或開啟動畫。
(4)onPause() ,可見狀態
此方法回撥時,Activity正在停止(Paused形態),通常接下來 onStop() 會被回撥 。但通過流程圖可見,另一種情況是onPause() 執行後直接執行了onResume方法,這可能是使用者點選Home鍵,讓程式退回到主介面,程式在後臺執行時又迅速地再回到到當前的Activity,此時onResume方法就會被回撥。我們可以在onPause方法中做一些資料儲存、動畫停止、資源回收等操作。另外,onPause方法執行完成後,新Activity的onResume方法才會被執行。所以onPause不能太耗時,因為這可能會影響到新的Activity的顯示。
(5)onStop() ,不可見狀態
此方法回撥時,Activity即將停止或者完全被覆蓋(Stopped形態),此時Activity不可見,僅在後臺執行。同樣地,在onStop方法可以做一些資源釋放的操作,不能太耗時。
(5) onRestart(),可見狀態
此方法回撥時,表示Activity正在重新啟動,由不可見狀態變為可見狀態。這種情況,一般發生在使用者打開了一個新的Activity時,之前的Activity就會被onStop,接著又回到之前Activity頁面時,之前的Activity的 onRestart方法就會被回撥。
(6)onDestroy() ,不可見狀態
此方法回撥時,表示Activity正在被銷燬,也是生命週期最後一個執行的方法,一般我們可以在此方法中做一些回收工作和最終的資源釋放。
三、問題思考(難度升級)
1、如果所有的初始化都在onCreate()中實現,會有什麼問題?
首先,Activity的onCreate()被呼叫時,Activity還不可見,如果要做一些動畫,既然檢視還不存在,在onCreate中來啟動動畫,明顯有問題;
其次,AActivity 切換到 BActivity,再切換到 AActivity,由於例項已經存在,所以onCreate不會再被呼叫,那問題就在於AActivity從後臺切換至前臺時,有可能需要一些初始化,就沒法被呼叫到了。
2、如果所有的初始化都在onStart()中實現,會有什麼問題?
首先,雖然 在onStart()中用 setContentView()、findViewById() 功能也是正常的,但是onCreate()註釋中,明確建議 setContentView()、findViewById() 要在 onCreate() 中被呼叫。
其次, onResume()的註釋中都明確地說了這不是 Activity 對使用者是可見的最好的指示器,如果在 onStart() 中做全部初始化,很有可能初始化還沒完成影響到使用者的互動體驗。
3、如果所有資源回收都在onStop()中實現,會有什麼問題?
首先,在 onResume() 的註釋中,建議是在onResume()中開啟獨佔裝置(比如相機),與onResume()對應的是onPause(),關閉相機的操作也應該在此方法中被呼叫;否則,考慮一下如下場景:如果AActivity打開了相機,我們點選某按鈕要跳轉到BActivity中,BActivity也想開啟相機;假設AActivity的onPause() 在 BActivity啟動後再被呼叫,那BActivity根本就無法再正常啟動相機。
在onPause() 的註釋中明確表示,應該在這個方法中執行停止動畫等比較耗CPU的操作,如果不先執行這些操作,就先啟動新應用,然後再來執行此操作,確實是不合邏輯;其次,onStop() 的註釋中也明確地寫了,在記憶體不足而導致系統自動回收程序情況下,onStop() 可能都不會被執行。
4、Activity間跳轉時,為什麼AActivity的onPause()被呼叫後,BActivity的初始化流程(onCreate() -> onStart() -> onResume()),然後AActivity的onStop()被呼叫?
從AActivity切換到BActivity的日誌如下:
10-17 20:54:46.997: I/com.example.servicetest.AActivity(5817): onPause()
10-17 20:54:47.021: I/com.example.servicetest.BActivity(5817): onCreate()
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onStart()
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onResume()
10-17 20:54:47.099: I/com.example.servicetest.AActivity(5817): onStop()
當用戶點選開啟新的Activity,肯定是想盡快進入新的檢視進行操作。而且上面的問題已經解釋了,在onResume()一般會開啟獨佔裝置,開啟動畫等,當需要從AActivity切換到BActivity時,先執行AActivity中的onPause()進行關閉獨佔裝置,關閉動畫等,以防止BActivity也需要使用這些資源,因為AActivity的資源回收,也有利於BActivity執行的流暢。
當AActivity中比較消耗資源的部分在onPause()中關閉後,再執行BActivity的初始化,顯示檢視與使用者互動。然後,系統在後臺默默執行AActivity的onStop()操作,去回收AActivity佔用的其餘資源。即使onStop()中會有些比較耗時的操作,也沒有關係,這是在後臺執行也不會影響到使用者的體驗。(設計的非常好!good!!!)
四、onSavedInstanceState()和onRestoreInstanceState()理解
大家在開發過程中可能遇到,當在頁面的EditText中輸入值,接著翻轉螢幕時,我輸入的內容清空了,但是當我給EditText定義了id屬性,再執行上訴操作時,EditText的內容仍然存在。另外,當我們點選Home鍵退回到主頁面,許久之後再次開啟程式進行操作,可能會崩潰。
下面解釋為什麼會出現這樣的情況:
(1)onSavedInstanceState()和onRestoreInstanceState()並不是activity生命週期的方法。
- onSaveInstanceState()會在onPause()或onStop()之前執行;
- onRestoreInstanceState()會在onStart()和onResume()之間執行。
當應用遇到意外情況(記憶體不足,使用者直接按home鍵)由系統直接銷燬一個Activity時,onSaveInstanceState()就會呼叫,但是當用戶主動銷燬activity,如按back鍵,或直接執行finish(),這種情況下onSaveInstanceState()就不會執行,因為這種情況下,使用者的行為決定了不需要儲存Activity的狀態。
(2)那麼onRestoreInstanceState()會跟onSaveInstanceState()成對出現嗎?
答案是不會成對出現,onSaveInstanceState()需要呼叫的時,activity可能銷燬,也可能沒有銷燬,只有在activity銷燬重建的時候onRestoreInstanceState()才會呼叫。