天天看點

Android四大元件生命周期

四大元件的生命周期

 介紹生命周期之前,先提一下任務的概念

任務其實就是activity 的棧它由一個或多個Activity組成的共同完成一個完整的使用者體驗, 換句話說任務就是” 應用程式” (可以是一個也可以是多個,比如假設你想讓使用者看到某個地方的街道地圖。而已經存在一個具有此功能的activity 了,那麼你的activity 所需要做的工作就是把請求資訊放到一個Intent 對象裡面,并把它傳遞給startActivity()。于是地圖浏覽器就會顯示那個地圖。而當使用者按下BACK 鍵的時候,你的activity 又會再一次的顯示在螢幕上,此時任務是由2個應用程式中的相關activity組成的)棧底的是啟動整個任務的Activity,棧頂的是目前運作的使用者可以互動的Activity,當一個activity 啟動另外一個的時候,新的activity 就被壓入棧,并成為目前運作的activity。而前一個activity 仍保持在棧之中。當使用者按下BACK 鍵的時候,目前activity 出棧,而前一個恢複為目前運作的activity。棧中儲存的其實是對象,棧中的Activity 永遠不會重排,隻會壓入或彈出,是以如果發生了諸如需要多個地圖浏覽器的情況,就會使得一個任務中出現多個同一Activity 子類的執行個體同時存在。

任務中的所有activity 是作為一個整體進行移動的。整個的任務(即activity 棧)可以移到前台,或退至背景。舉個例子說,比如目前任務在棧中存有四個activity──三個在目前activity 之下。當使用者按下HOME 鍵的時候,回到了應用程式加載器,然後選擇了一個新的應用程式(也就是一個新任務)。則目前任務遁入背景,而新任務的根activity 顯示出來。然後,過了一小會兒,使用者再次回到了應用程式加載器而又選擇了前一個應用程式(上一個任務)。于是那個任務,帶着它棧中所有的四個activity,再一次的到了前台。當使用者按下BACK 鍵的時候,螢幕不會顯示出使用者剛才離開的activity(上一個任務的根

activity)。取而代之,目前任務的棧中最上面的activity 被彈出,而同一任務中的上一個activity 顯示了出來。

Activity棧:先進先出規則

Android系統是一個多任務(Multi-Task)的作業系統,可以在用手機聽音樂的同時,也執行其他多個程式。每多執行一個應用程式,就會多耗費一些系統記憶體,當同時執行的程式過多,或是關閉的程式沒有正确釋放掉記憶體,系統就會覺得越來越慢,甚至不穩定。

為了解決這個問題, Android 引入了一個新的機制– 生命周期(Life Cycle)。

Android 應用程式的生命周期是由Android 架構進行管理,而不是由應用程式直接控

制。通常,每一個應用程式(入口一般會是一個Activity 的onCreate 方法),都會産生

一個程序(Process)。當系統記憶體即将不足的時候,會依照優先級自動進行程序(process)的回收。不管是使用者或開發者, 都無法确定的應用程式何時會被回收。是以為了很好的防止資料丢失和其他問題,了解生命周期很重要。

Activity整個生命周期的4種狀态、7個重要方法和3個嵌套循環

1> 四種狀态

  活動(Active/Running)狀态

當Activity運作在螢幕前台(處于目前任務活動棧的最上面),此時它擷取了焦點能響應使用者的操作,屬于運作狀态,同一個時刻隻會有一個Activity 處于活動(Active)或運作

(Running)狀态

暫停(Paused)狀态

當Activity失去焦點但仍對使用者可見(如在它之上有另一個透明的Activity或Toast、AlertDialog等彈出視窗時)它處于暫停狀态。暫停的Activity仍然是存活狀态(它保留着所有的狀态和成員資訊并保持和視窗管理器的連接配接),但是當系統記憶體極小時可以被系統殺掉

    停止(Stopped)狀态

完全被另一個Activity遮擋時處于停止狀态,它仍然保留着所有的狀态和成員資訊。隻是對使用者不可見,當其他地方需要記憶體時它往往被系統殺掉

    非活動(Dead)狀态

Activity 尚未被啟動、已經被手動終止,或已經被系統回收時處于非活動的狀态,要手動終止Activity,可以在程式中調用”finish”方法。

如果是(按根據記憶體不足時的回收規則)被系統回收,可能是因為記憶體不足了

記憶體不足時,Dalvak 虛拟機會根據其記憶體回收規則來回收記憶體:

  1. 先回收與其他Activity 或Service/Intent Receiver 無關的程序(即優先回收獨

立的Activity)是以建議,我們的一些(耗時)背景操作,最好是作成Service的形式

  2.不可見(處于Stopped狀态的)Activity

  3.Service程序(除非真的沒有記憶體可用時會被銷毀)

  4.非活動的可見的(Paused狀态的)Activity

  5.目前正在運作(Active/Running狀态的)Activity

2> 7個重要方法,當Activity從一種狀态進入另一狀态時系統會自動調用下面相應的方

法來通知使用者這種變化

當Activity第一次被執行個體化的時候系統會調用,

整個生命周期隻調用1次這個方法

通常用于初始化設定: 1、為Activity設定所要使用的布局檔案2、為按鈕綁定監聽器等靜态的設定操作

  onCreate(Bundle savedInstanceState);

當Activity可見未獲得使用者焦點不能互動時系統會調用

  onStart();

當Activity已經停止然後重新被啟動時系統會調用

  onRestart();

當Activity可見且獲得使用者焦點能互動時系統會調用

  onResume();

當系統啟動另外一個新的Activity時,在新Activity啟動之前被系統調用儲存現有的Activity中的持久資料、停止動畫等,這個實作方法必須非常快。當系統而不是使用者自己出于回收記憶體時,關閉了activity 之後。使用者會期望當他再次回到這個activity 的時候,它仍保持着上次離開時的樣子。此時用到了onSaveInstanceState(),方法onSaveInstanceState()用來儲存Activity被殺之前的狀态,在onPause()之前被觸發,當系統為了節省記憶體銷毀了Activity(使用者本不想銷毀)時就需要重寫這個方法了,當此Activity再次被執行個體化時會通過onCreate(Bundle savedInstanceState)将已經儲存的臨時狀态資料傳入因為onSaveInstanceState()方法不總是被調用,觸發條件為(按下HOME鍵,按下電源按鍵關閉螢幕,橫豎屏切換情況下),你應該僅重寫onSaveInstanceState()來記錄activity的臨時狀态,而不是持久的資料。應該使用onPause()來存儲持久資料。

  onPause();

當Activity被新的Activity完全覆寫不可見時被系統調用

  onStop();

當Activity(使用者調用finish()或系統由于記憶體不足)被系統銷毀殺掉時系統調用,(整個生命周期隻調用1次)用來釋放onCreate ()方法中建立的資源,如結束線程等

  onDestroy();

3> 3個嵌套循環

         1.Activity完整的生命周期:從第一次調用onCreate()開始直到調用onDestroy()結束

         2.Activity的可視生命周期:從調用onStart()到相應的調用onStop()

                在這兩個方法之間,可以保持顯示Activity所需要的資源。如在onStart()中注冊一個廣播接收者監聽影響你的UI的改變,在onStop() 中登出。

         3.Activity的前台生命周期:從調用onResume()到相應的調用onPause()。

  舉例說明:

例1:有3個Acitivity,分别用One,Two(透明的),Three表示,One是應用啟動時的主Activity

  啟動第一個界面Activity One時,它的次序是

         onCreate (ONE) - onStart (ONE) - onResume(ONE)

  點"打開透明Activity"按鈕時,這時走的次序是

         onPause(ONE) - onCreate(TWO) - onStart(TWO) - onResume(TWO)

  再點back回到第一個界面,Two會被殺這時走的次序是

         onPause(TWO) - onActivityResult(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO)

  點"打開全屏Activity"按鈕時,這時走的次序是

         onPause(ONE) - onCreate(Three) - onStart(Three) - onResume(Three) - onStop(ONE)

  再點back回到第一個界面,Three會被殺這時走的次序是

         onPause(Three) - onActivityResult(ONE) - onRestart(ONE) - onStart(ONE)- onResume(ONE) - onStop(Three) - onDestroy(Three)

  再點back退出應用時,它的次序是

         onPause(ONE) - onStop(ONE) - onDestroy(ONE)           

例2:橫豎屏切換時候Activity的生命周期

他切換時具體的生命周期是怎麼樣的:

1、建立一個Activity,并把各個生命周期列印出來

2、運作Activity,得到如下資訊

onCreate–>

onStart–>

onResume–>

3、按crtl+f12切換成橫屏時

onSaveInstanceState–>

onPause–>

onStop–>

onDestroy–>

onCreate–>

onStart–>

onRestoreInstanceState–>

onResume–>

4、再按crtl+f12切換成豎屏時,發現列印了兩次相同的log

onSaveInstanceState–>

onPause–>

onStop–>

onDestroy–>

onCreate–>

onStart–>

onRestoreInstanceState–>

onResume–>

onSaveInstanceState–>

onPause–>

onStop–>

onDestroy–>

onCreate–>

onStart–>

onRestoreInstanceState–>

onResume–>

5、修改AndroidManifest.xml,把該Activity添加android:configChanges=”orientation”,執行步驟3

onSaveInstanceState–>

onPause–>

onStop–>

onDestroy–>

onCreate–>

onStart–>

onRestoreInstanceState–>

onResume–>

6、再執行步驟4,發現不會再列印相同資訊,但多列印了一行onConfigChanged

onSaveInstanceState–>

onPause–>

onStop–>

onDestroy–>

onCreate–>

onStart–>

onRestoreInstanceState–>

onResume–>

onConfigurationChanged–>

7、把步驟5的android:configChanges=”orientation” 改成 android:configChanges=”orientation|keyboardHidden”,執行步驟3,就隻列印onConfigChanged

onConfigurationChanged–>

8、執行步驟4

onConfigurationChanged–>

onConfigurationChanged–>

總結:

1、不設定Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次

2、設定Activity的android:configChanges=”orientation”時,切屏還是會重新調用各個生命周期,切橫、豎屏時隻會執行一次

3、設定Activity的android:configChanges=”orientation|keyboardHidden”時,切屏不會重新調用各個生命周期,隻會執行onConfigurationChanged方法

總結一下整個Activity的生命周期

補充一點,目前Activity産生事件彈出Toast和AlertDialog的時候Activity的生命周期不會有改變

Activity運作時按下HOME鍵(跟被完全覆寫是一樣的):onSaveInstanceState –> onPause –> onStop,再次進入激活狀态時: onRestart –>onStart—>onResume

BroadcastReceive廣播接收器生命周期:

生命周期隻有十秒左右,如果在 onReceive() 内做超過十秒内的事情,就會報ANR(Application No Response) 程式無響應的錯誤資訊

它的生命周期為從回調onReceive()方法開始到該方法傳回結果後結束

Service服務生命周期:

Service完整的生命周期:從調用onCreate()開始直到調用onDestroy()結束

Service有兩種使用方法:

1>以調用Context.startService()啟動,而以調用Context.stopService()結束

2>以調用Context.bindService()方法建立,以調用Context.unbindService()關閉

service重要的生命周期方法

當使用者調用startService ()或bindService()時,Service第一次被執行個體化的時候系統會調用,整個生命周期隻調用1次這個方法,通常用于初始化設定。注意:多次調用startService()或bindService()方法不會多次觸發onCreate()方法

void onCreate()

當使用者調用stopService()或unbindService()來停止服務時被系統調用,(整個生命周期隻調用1次)用來釋放onCreate()方法中建立的資源

void onDestroy()

通過startService()方法啟動的服務

  初始化結束後系統會調用該方法,用于處理傳遞給startService()的Intent對象。如音樂服務會打開Intent 來探明将要播放哪首音樂,并開始播放。注意:多次調用startService()方法會多次觸發onStart()方法

void onStart(Intent intent)

通過bindService ()方法啟動的服務

  初始化結束後系統會調用該方法,用來綁定傳遞給bindService 的Intent 的對象。注意:多次調用bindService()時,如果該服務已啟動則不會再觸發此方法

IBinder onBind(Intent intent)

使用者調用unbindService()時系統調用此方法,Intent 對象同樣傳遞給該方法

boolean onUnbind(Intent intent)

如果有新的用戶端連接配接至該服務,隻有當舊的調用onUnbind()後,新的才會調用該方法

void onRebind(Intent intent)

補充:onCreate(Bundle savedInstanceState)與onSaveInstanceState(Bundle savedInstanceState)配合使用,見如下代碼,達到顯示activity被系統殺死前的狀态