Android Activity的生命周期詳解


應用程序中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控件也可以監聽並處理用戶的事件做出響應。

Activity之間通過Intent進行通信。在Intent 的描述結構中,有兩個最重要的部分:動作和動作對應的數據。

典型的動作類型有:M AIN(activity的門戶)、VIEW、PICK、EDIT 等。而動作對應的數據則以URI 的形式進行表示。例如:要查看一個人的聯系方式,你需要創建一個動作類型為VIEW 的intent,以及一個表示這個人的URI。

與之有關系的一個類叫IntentFilter。相對於intent 是一個有效的做某事的請求,一個intentfilter 則用於描述一個activity(或者IntentReceiver)能夠操作哪些intent。一個activity 如果要顯示一個人的聯系方式時,需要聲明一個IntentFilter,這個IntentFilter 要知道怎么去處理VIEW 動作和表示一個人的URI。IntentFilter 需要在AndroidManifest.xml 中定義。通過解析各種intent,從一個屏幕導航到另一個屏幕是很簡單的。當向前導航時,activity 將會調用startActivity(Intent myIntent)方法。然后,系統會在所有安裝的應用程序中定義的IntentFilter 中查找,找到最匹配myIntent 的Intent 對應的activity。新的activity 接收到myIntent 的通知后,開始運行。當startActivity 方法被調用將觸發解析myIntent 的動作,這個機制提供了兩個關鍵好處:

A、Activities 能夠重復利用從其它組件中以Intent 的形式產生的一個請求;

B、Activities 可以在任何時候被一個具有相同IntentFilter 的新的Activity 取代。

AndroidManifest文件中含有如下過濾器的Activity組件為默認啟動類當程序啟動時系統自動調用它

<intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

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

任務其實就是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>   四種狀態

  1.       活動(Active/Running)狀態

當Activity運行在屏幕前台(處於當前任務活動棧的最上面),此時它獲取了焦點能響應用戶的操作,屬於運行狀態,同一個時刻只會有一個Activity 處於活動(Active)或運行

(Running)狀態

  1.     暫停(Paused)狀態

當Activity失去焦點但仍對用戶可見(如在它之上有另一個透明的Activity或Toast、AlertDialog等彈出窗口時)它處於暫停狀態。暫停的Activity仍然是存活狀態(它保留着所有的狀態和成員信息並保持和窗口管理器的連接),但是當系統內存極小時可以被系統殺掉

3.      停止(Stopped)狀態

完全被另一個Activity遮擋時處於停止狀態,它仍然保留着所有的狀態和成員信息。只是對用戶不可見,當其他地方需要內存時它往往被系統殺掉

4.      非活動(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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM