Android面試之Activity生命週期詳解

Activity生命週期詳解

一 Activity的四種狀態:

Activity的生命週期中存在四種基本的狀態:活動狀態(Active/Runing),暫停狀態(Paused),停止狀態(Stopped),銷燬狀態(Killed)。每個狀態下Activity都會擁有某些能力和失去某些能力。

  • 活動狀態(Active/Runing)

    一個新的Activity入棧之後,當處於Activity的棧頂,此時它處於可見並且能與用戶交互的激活狀態,叫做活動狀態或者運行狀態。

    期間觸發的生命週期有: onCreate() -> onStart() -> onResume()。

  • 暫停狀態(Paused)

    當Activity是去焦點,一個新的非全屏的Activity或者一個透明的Activity被放置在棧頂。注意:在Activity之上顯示Dialog或者PoupWindow的時候,該Activity並不會變成暫停狀態。一個處於暫停狀態下的Activity只有再通極度匱乏的時候纔會被回收掉。

    運行狀態到暫停狀態觸發的生命週期:onResume() -> onPause()。

    從暫停狀態恢復到運行狀態觸發的生命週期:onPause() -> onResume()。

  • 停止狀態(Stopped)

    一個Activity被另外一個Activity完全覆蓋掉,用戶不可見或者退至後臺,叫做停止狀態。它仍然保持這所有狀態跟成員信息,不能與用戶交互。當系統內存需要的時候Stopped狀態的Activity會被強制回收掉。

    從暫停到停止狀態觸發的生命週期:onPause() -> onStop()。

    從停止狀態到運行狀態觸發的生命週期:onStop() -> onRestart() -> onStart() -> onResume()。不會走onCreate()。

  • 銷燬狀態(Killed)

    如果一個Activity再Paused或者Stopped狀態,系統可以將Activity從內存中刪除,刪除的方式有兩種:一種是要求Activity結束,一種直接結束掉它的進程。當有需要的時候就得重新創建Activity了。

    觸發的生命週期:onDestroy(),直接結束進程的話是不會走onDestroy()的。

上面是Activity在整個生命週期中展示的四種狀態。程序員可以手動創建一個Activity,但不能手動的銷燬一個Activity。也就是說當調用activity.finish()方法或者按下物理返回鍵去關掉一個Activity的時候,只是通知了AntivityManager該Activity可以被回收了,隨後ActivityManage將採取一系列的回收措施,這是開發者無法干預的。

二 完整的生命週期:

Activity完整的生命週期 :

oncreate()->onstart()->onResume()->onRestart()->onPouse()->onStop()->onDestory()。

Activity在創建到銷燬的過程中會走的完整的生命週期,但是並一定每次創建跟銷燬都會完整的走一遍。

圖是百度百科的

  • oncreate()

    Activity創建的時候第一個走的生命週期。這個生命週期中可以做一些初始化的工作:調用setContentView()去加載UI試圖,可以用findViewById跟佈局裏面的組件進行交互,調用managedQuery(),使用Bundle恢復數據等等方法。系統表示在該方法內應該調用setContentView()和進行findViewById的操作,當然別的生命週期也是可以調用setContentView()和進行findViewById()操作的。大多情況下頁面的數據是只需要初始化一次,那麼也就必須在onCreate()方法中去初始化,這也就是爲啥我們老是在onCreate()方法中去加載我們需要的組件。

    特點: 不可見,不可交互,可初始化數據。

    注意: onCreate()生命週期中直接執行onFinish()方法的時候,Activity將直接被調用onDestroy()方法不會走其他的生命週期。Activity在調用過該方法之後纔會調用onStart方法,順序執行,所以不要在該方法中做一些耗時的工作,影響界面的啓動速度。

  • onStart()

    在onCreate()方法之後調用或者onRestart()之後。源碼並沒有對此方法做過多的解釋,只是說有兩個地方會執行到該方法:一次是創建的時候,一次是暫停狀態到活動狀態的時候。這個方法開發中勇的不多,適合開啓在Activity活躍狀態下才要執行的任務:開始計時,接口輪詢,啓動廣播,開啓後臺任務等。該方法不適合大量的數據初始化,因爲它會執行多次。

    特點: 可見,不可交互,如果在onCreate()方法中完成數據的初始化這時就可以直接操作數據了。

    注意: 整個Activity生命週期中可別執行多次,切記一定要正確的使用該聲明週期。

  • onResume()

    再onStart(),onRestoreInstanceState(),onRestart(),onPause()方法之後都會執行onResume()。源碼註釋說這裏建議開啓動畫,或者打開一些獨享設備(照相機)等的操作。該方法會在Activity的整個生命週期中頻繁的調用,寫在裏面的邏輯要非常的慎重。常見的功能:當頁面可見的時候刷新頁面的數據,這個雖然會浪費資源但是有的時候確實很有用的。一般爲了控制某些代碼在該生命週期裏面只執行一次,可以添加一個標記爲去控制一下,也是一個不錯的選擇,畢竟當用戶可見的時候這個方法就會被執行一次…

    特點: 可見,可交互,Activity位於的活動棧頂部。

    注意: 該方法會頻繁的調用,慎重節約資源。

  • onPause()

    當Activity是去焦點後會被調用,頁面被透明的活着半透明的Activiy部分遮擋。該方法調用可能是Activity要被銷燬,也可能是頁面進入後臺。被調用的頻率不算很多,適合保存一些持久化數據,比如EditText的展示數據恢復,停止一些動畫和一些消耗cpu的任務,或者關閉獨佔訪問的資源等(如:相機)等。該方法嚐嚐伴隨着onStop()執行但也有情況直接調用onResume()方法。開發中都沒怎麼用到過該方法…

    特點: 可見,不可交互,可以被系統回收。

    注意: 該方法常再Activity處於停止狀態下調用,當啓動另一個Activity的時候,新啓動的Activity必須等到該Activity的onPause()方法執行纔會執行自己的onCreate()…等方法。所以不要在該方法裏面做耗時的操作以免影響啓動新Activity的效率。另外就算是Activity被系統強制的回收也一定會走這個方法,可以不走onDestroy()。

  • onStop()

    當Activity不可見的時候調用。此時Activity處於停止狀態,當頁面被完全遮擋,按下Home建頁面進入後臺,Activity銷燬等。該方法適合停止一些消耗資源的操作:結束倒計時,接口數據輪訓,取消註冊的廣播,關閉後臺的服務等。但是千萬不要再該方法中釋放一些運行狀態下要用到的一些數據。之前做過在onStop的時候將一個引用置爲NULL來回收資源,就是因爲看到了文章說建議在這個聲明週期內回收資源,結果可想而知…

    該方法之後會調用onRestart() -> onStart() -> onResume()。或者調用onDestroy()。

    特點: 不可見,不可交互,可以被系統回收。

    注意: 釋放Activity持有的資源要慎重,有網絡輪詢儘量關掉輪詢,切斷倒計時或者一些單個網絡請求等。當Activity被強制回收內存的時候Android版本是3.0之後該方法也是一定會走的,可以不走onDestroy()。

  • onDestroy()

    在Activity的整個生命週期中只會執行一次,也就是Activity將要被銷燬的時候,通常是調用了finish()方法或者系統內存不足強制銷燬。在這裏一般要進行持有資源的全部釋放工作,將集合清空,引用置爲null,銷燬一些單例,取消網絡請求,以及清空Handler數據等等,保證不會出現內存泄漏的情況。可以調用Activity.isFinish去判斷該Activity是否已經銷燬。不要嘗試再該方法中去保存一些數據,這只是系統的警告,我們還是會再該方法裏面去保存一些SP數據的…另外:在某些情況下,系統會簡單地終止活動的宿主進程,而不調用其中的此方法(或任何其他方法),因此不應將其用於執行進程結束後要保留重要數據的操作。

    特定: 可以放心的回收資源。

    注意: 在回收資源的時候也要進行一些判空,以免發生意外。儘量不要再該方法裏面去保存一下重要的數據。界面被系統回收的時候該方法可能不會被調用。

三 常見的生命週期的問題

1.當前Activity啓動另外一個Activity,啓動之後關掉新Activity的時候兩個生命週期的變化:

ActivityA 啓動 Activity B :

ActivityA : onPause() -> ActivityB :onCreate() -> ActivityB:onStart() -> ActivityB :onResume() -> ActivityA : onStop()。

這也就是打開一個新的Activity一定要等當前的Activity的onPause()方法走完之後纔會去創建新的Activity。

2.屏幕旋轉:

Activity :onpause() -> onStop() -> onCreate() -> onStart() -> onResume()。

當屏幕旋轉的時候Activity會銷燬創建,這一點一定要記得,如果Activity發生泄漏的話旋轉次數多了就會導致內存佔用越多最終導致OOM。

另外屏幕旋轉將會導致佈局拉伸或者壓縮,嚴重影響UI界面美觀性,除非你已經做了適配。建議直接將界面設置成不可旋轉的吧。

3.按home鍵:

Activity進入後臺 : onPause() -> onStop() 。回到前臺:onRestart() -> onStart() -> onResume()。

有可能應用會被系統殺死進程。

4.系統回收:

首先每個應用最少有一個進程,我們的Activity都是運行在進程中的,當應用退到後臺時,系統可能因爲內存不足而殺掉優先級低的進程,那麼再該進程中的Activity都會被殺死,這種情況是不會走Activity的生命週期的,只有殺掉單個Activity的時候纔會走Activity的onDestroy()方法。

5.調用finish方法:

調用finish()方法的時候需要區分在那個生命週期內執行的該方法,這裏是執行並不是在那個生命週期內寫了finishi()的代碼。

onCreate()生命週期內直接執行了finish()方法: onCreate() -> onDestroy()。

onStart()生命週期內直接執行了finish()方法: onCreate() -> onStart() -> onStop() -> onDestroy()。

onResume()生命週期內直接執行了finish()方法:onCreate() -> onStart() -> onResume() -> onPause()

-> onStop() -> onDestroy()。

注意點擊事件是觀察者模式,當執行的時候Activity一定onResume了。

6.物理返回鍵onKeyDown方法:

Activity : onpause() -> onStop() -> onDestroy()。

7.onSaveInstanceState()方法:

google工程師們對onSaveInstanceState如此設計就是讓其完成對一些臨時的、非永久數據存儲並進行恢復。什麼樣的數據屬於臨時數據呢?舉個例子,比如EditText中輸入的內容,CheckBox是否勾選,ScrollView的滑動位置,目前視頻的播放位置等等。
由於onSaveInstanceState()方法方法不一定會被調用(如:主動點擊back按鍵時), 因此不適合在該方法中保存持久化數據,例如向數據庫中插入記錄等。保存持久化數據的操作應該放在onPause()中。 onSaveInstanceState()方法只適合保存瞬態數據, 比如UI控件的狀態,,成員變量的值等。當Activity被系統回收的時候是一定會走這個方法的,所以可以再該方法的Bundle裏面保存一些數據用來重新恢復。

8.Dialog,PopupWindow或者DialogActivity:

當Activity之上顯示出Dialog或者PopupWindow的時候是不會走任何的生命週期的,Toast也是一樣的。當出現了Dialog風格的Activity的時候會走 onPause() -> onSaveInstanceState()。消失後會走onResume()。

9.息屏時再打開:

Activity : onPause() -> onStop() -> onRestart() -> onStart() -> onResume()。

10.再Activity的生命週期內直接調startActivity(Intent)方法:

AActivity再onPause()生命週期前調用啓動BActivity :

AActivity : onCreate() -> AActivity:onStart -> AActivity : onResume -> AActivity : onPause -> BActivity : onCreate() -> BActivity : onStart() -> BActivity : onResume().

也就是打開一個新的Activity一定要等到當前的Activity的onPasuse()生命週期走過。這一點其實很有用的,比如當我們想要在界面一開始的時候做一些操作,然後直接跳到別的界面,在onCreate()裏面寫了跳轉邏輯,之後又寫了一大堆的邏輯代碼,最後反而影響了新界面的打開速度。最好是加個Return,讓後面的邏輯代碼不執行。

11.啓動一個再前臺的且啓動模式爲singleTop的Activity:

Activity : onPause() -> onNewIntent() -> onResume()。

12.再當前Activity界面進入設置界面更改了一些已有的設置,或者Activity發生異常奔潰重建:

Activity : onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() (會執行這個方法onRestoreInstance() )-> onResume()。

歡迎點擊關注哦

我的GitHub裏面有好多適合學習的框架,都是按照最流行的框架來的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章