Activity的生命週期和啓動模式

這篇文章大部份內容來自Activity的全方面解析,本文只是往加上Activity的全方面解析這篇文章沒法 顯示的圖片和一些沒有介紹的部分基礎內容html

生命週期

正常時候的生命週期

如圖所示,在正常狀況下,一個Activity從啓動到結束會以以下順序經歷整個生命週期:android

  1. onCreate():當 Activity 第一次建立時會被調用。這是生命週期的第一個方法。在這個方法中,能夠作一些初始化工做,好比調用setContentView去加載界面佈局資源,初始化Activity所需的數據。git

  2. onRestart():表示Activity正在從新啓動。通常狀況下,當前Activity從不可見從新變爲可見狀態時,onRestart就會被調用。這種情形通常是用戶行爲致使的,好比用戶按Home鍵切換到桌面或打開了另外一個新的Activity,接着用戶又回到了這個Actvity。ide

  3. onStart(): 表示Activity正在被啓動,即將開始,這時Activity已經出現了,可是尚未出如今前臺,沒法與用戶交互。這個時候能夠理解爲Activity已經顯示出來,可是咱們還看不到。佈局

  4. onResume():表示Activity已經可見了,而且出如今前臺並開始活動。須要和onStart()對比,onStart的時候Activity還在後臺,onResume的時候Activity才顯示到前臺。ui

  5. onPause():表示 Activity正在中止,仍可見,正常狀況下,緊接着onStop就會被調用。在特殊狀況下,若是這個時候快速地回到當前Activity,那麼onResume就會被調用(極端狀況)。onPause中不能進行耗時操做,會影響到新Activity的顯示。由於onPause必須執行完,新的Activity的onResume纔會執行。spa

  6. onStop():表示Activity即將中止,不可見,位於後臺。能夠作稍微重量級的回收工做,一樣不能太耗時。code

  7. onDestory():表示Activity即將銷燬,這是Activity生命週期的最後一個回調,能夠作一些回收工做和最終的資源回收cdn

常見情景

  1. 當咱們看新聞時,出現電話、信息等通知,此時activity不會調用生命週期的方法,只有你點擊通知跳轉到其餘activity時,纔會調用onPause->onStop方法xml

  2. 當咱們按Home鍵切換到桌面後又回到該Actitivy,回調以下:onPause()->onStop()->onRestart()->onStart()->onResume()

  3. 當咱們按back鍵回退時,回調以下:onPause()->onStop()->onDestory()

  4. 在生命週期方法中調用finish()時,activity的生命週期與調用finish()的位置有關(調用完finish()後,不會直接退出該生命週期的方法,而是先執行完所在的生命週期方法):

  • onCreate()中調用時,先執行完onCreate(),回調爲onDestory()
  • onStart()中調用時,回調爲:onStop()->onDestory()
  • onResume()中執行時,回調爲:onPause()->onStop()->onDestory()
  • onPause()中執行時,回調爲:onStop()->onDestory()
  • onStop()中調用時,回調爲:onDestory()

異常時候的生命週期

橫豎屏切換

橫豎屏切換的生命週期回調爲:onPause()->onSaveInstanceState()-> onStop()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState->onResume()

onSaveInstanceState()用來在橫豎屏切換時保存當前activity的狀態,當activity重建時,系統會而且把Activity銷燬時onSaveInstanceState方法所保存的Bundle對象參數同時傳遞給onRestoreInstanceStateonCreate方法.(onCreateonRestoreInstanceState的區別就是onCreate傳遞過來的Bundle對象可能爲null,而onRestoreInstanceState的不會爲null)

AndroidManifest.xmlactivity中禁用橫豎屏切換

android:configChanges = "orientation| screenSize"
複製代碼

此時,不會進行橫豎屏切換,而是調用onConfigurationChanged(Configuration newConfig)方法。

資源內存不足致使優先級低的Activity被殺死

Activity的優先級從高到低,可分爲以下三種:

  1. 前臺Activity: 正在和用戶交互的Activity
  2. 可見但非前臺Activity:好比Activity中彈出了一個對話框,致使Activity可見可是位於後臺沒法和用戶交互
  3. 後臺Activity——已經被暫停的Activity,好比執行了onStop,優先級最低

當系統內存不足時,會按照上述優先級從低到高去殺死目標Activity所在的進程。

Activity的啓動模式

啓動模式的結構——棧

Activity的管理是採用任務棧的形式,任務棧採用「後進先出」的棧結構。

任務棧

Android的任務棧由TaskAffinity指定,TaskAffinity標識了一個Activity所須要的任務棧的名字。默認狀況下TaskAffinity爲包名。通常咱們不改變TaskAffinity的默認值,不一樣的應用屬於不一樣的任務棧,同一個應用都在同一個任務棧。咱們能夠經過設置TaskAffinity來讓同一應用中的不一樣的Activity屬於不一樣的任務棧。

前臺任務棧和後臺任務棧的區別:前臺任務棧和後臺任務棧都是任務棧,不一樣的是前臺任務棧中存在Activity與爲用戶所見,然後臺的任務棧中的Activity都在後臺

啓動模式的類別

Android提供了四種Activity啓動方式:

  • 標準模式(standard)
  • 棧頂複用模式(singleTop)
  • 棧內複用模式(singleTask)
  • 單例模式(singleInstance)

標準模式(standard)

每啓動一次Activity,就會建立一個新的Activity實例並置於棧頂。誰啓動了這個Activity,那麼這個Activity就運行在啓動它的那個Activity所在的棧中。

特殊狀況:

  1. 假設有應用A和應用B,A啓動另外一個應用B的MainActivity(入口Activity)時,會建立一個新的任務棧,並將另外一個應用的Activity置於這個新棧中。若是啓動另外一個應用的非入口Activity(此時這個被啓動Activity要求android:exported屬性爲true),則會將這個應用B的Activity放在應用A的棧中

  2. 若是在Service或Application中啓動一個Activity,其並無所謂的任務棧,能夠爲待啓動的Activity指定FLAG_ACTIVITY_NEW_TASK標記位,建立一個新棧。

注意在5.0以前A啓動另外一個應用B的MainActivity(入口Activity)時,新啓動的Activity實例會放入發送Intent的Task的棧的頂部,儘管它們屬於不一樣的程序

棧頂複用模式(singleTop)

若是須要新建的Activity位於任務棧棧頂,那麼此Activity的實例就不會重建,而是重用棧頂的實例,此時會調用ActivityonNewIntent(Intent intent)方法。若是棧頂不是新建的Activity,就會建立該Activity新的實例,並放入棧頂。

注意:在Android 5.0以前,若是是外部程序啓動singleTop的Activity,新建立的Activity會位於調用者的Task中,5.0及之後會放入新的Task中。

棧內複用模式(singleTask)

該模式是一種單例模式,即一個棧內只有一個該Activity實例。該模式,能夠經過在AndroidManifest.xml文件的taskAffinity屬性指定該Activity須要加載到那個棧中。若是Activity指定的棧不存在,則建立一個棧,並把建立的Activity壓入棧內。若是Activity指定的棧存在,若是其中沒有該Activity實例,則會建立Activity並壓入棧頂,若是其中有該Activity實例,則把該Activity實例之上的其餘Activity殺死清除出棧,重用並讓該Activity實例處在棧頂,而後調用onNewIntent()方法。

單例模式(singleInstance)

做爲棧內複用模式(singleTask)的增強版,打開該Activity時,直接建立一個新的任務棧,並建立該Activity實例放入新棧中。一旦該模式的Activity實例已經存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例。

啓動模式的應用

  • 標準模式(standard):通常的Activity
  • 棧頂複用模式(singleTop):在通知欄點擊收到的通知,而後須要啓動一個Activity,這個Activity就能夠用singleTop,不然每次點擊都會新建一個Activity。
  • 棧內複用模式(singleTask):大多數App的主頁。對於大部分應用,當咱們在主界面點擊回退按鈕的時候都是退出應用,那麼當咱們第一次進入主界面以後,主界面位於棧底,之後無論咱們打開了多少個Activity,只要咱們再次回到主界面,都應該使用將主界面Activity上全部的Activity移除的方式來讓主界面Activity處於棧頂,而不是往棧頂新加一個主界面Activity的實例,經過這種方式可以保證退出應用時全部的Activity都能報銷燬。
  • 單例模式(singleInstance):呼叫來電界面,不經常使用

特殊狀況——前臺棧和後臺棧的交互

假如目前有兩個任務棧。前臺任務棧爲AB,後臺任務棧爲CD,這裏假設CD的啓動模式均爲singleTask,如今請求啓動D,那麼這個後臺的任務棧都會被切換到前臺,這個時候整個後退列表就變成了ABCD。當用戶按back返回時,列表中的activity會一一出棧,

若是不是請求啓動D而是啓動C,那麼狀況又不同,這個時候整個後退列表就變成了ABC

Activity的Flags

Activity的Flags不少,這裏介紹集中經常使用的,用於設定Activity的啓動模式。能夠在啓動Activity時,經過Intent的addFlags()方法設置。

  • FLAG_ACTIVITY_NEW_TASK 其效果與指定Activity爲singleTask模式一致。
  • FLAG_ACTIVITY_SINGLE_TOP 其效果與指定Activity爲singleTop模式一致。
  • FLAG_ACTIVITY_CLEAR_TOP 具備此標記位的Activity,當它啓動時,在同一個任務棧中全部位於它上面的Activity都要出棧。若是和singleTask模式一塊兒出現,若被啓動的Activity已經存在棧中,則清除其之上的Activity,並調用該Activity的onNewIntent方法。若是被啓動的Activity採用standard模式,那麼該Activity連同之上的全部Activity出棧,而後建立新的Activity實例並壓入棧中。
相關文章
相關標籤/搜索