正常狀況下的Activity生命週期以下圖所示(來自Android Developer):3d
當資源相關的系統配置變動時(好比設備屏幕方向改變,鍵盤可見性變化),會致使Activity的銷燬與重建。某些系統配置變動時,系統會根據最新配置從新爲應用加載適合於當前配置的資源,這些系統配置就是資源相關的系統配置。此時在銷燬Activity前會調用onSaveInstance()方法已保存當前的狀態信息,這個方法會在onStop()前被調用,但與onPause()的時序關係不肯定。當Activity被從新建立後,onRestoreInstanceState()方法會被調用以恢復以前保存的狀態信息,這個方法具體的調用時機是在onStart()以後。blog
onSaveInstanceState()方法只有在被銷燬的Activity隨後會從新被建立時纔會被調用,主要有以下兩種狀況:生命週期
一個就是咱們上面提到的資源相關的系統配置變動時;內存
另外一個狀況就是系統內存不足致使低優先級的Activity被殺死,這種狀況下系統在銷燬Activity時會調用onSaveInstanceState()方法,而且隨後當被殺死的Activity從新啓動時,onRestoreInstanceState()方法會被回調。ci
在介紹Activity前,咱們先簡單地介紹一下任務棧(back stack)的概念。假設咱們從桌面首次啓動了某個App,系統會開啓一個新的任務棧並把該App的MainActivity(設爲Activity1)加入這個任務棧中,若以後咱們在新啓動的App中又打開了Activity 二、Activity 3,則Activity 2和Activity 3也會被依次壓入這個任務棧中。因而如今任務棧的棧頂就是Activity 3了,咱們與之交互的Activity始終是當前任務棧棧頂的Activity。如今咱們點擊了Back鍵,則Activity 3會被彈出任務棧,當前棧頂的Activity即變爲了Activity 2,咱們開始與Activity 2進行交互。資源
以上過程可用下圖來描述:開發
(1)standard:標準模式(默認)it
以standard模式啓動的Activity會被放入啓動它的那個Activity所在的任務棧(Back Stack)中。在咱們調用Context.startActivity方法去啓動standard模式的Activity時會報錯, 由於ApplicationContext並無關聯一個任務棧,解決方案是爲待啓動Activity指定FLAG_ACTIVITY_NEW_TASK標記位,此時會新鍵一個任務棧,並把剛啓動的Activity放入其中,這種狀況下被啓動Activity實際上以singleTask模式啓動。以standard模式啓動Activity的話,若屢次啓動會建立多個Activity實例。io
(2)singleTop:棧頂複用模式class
若待啓動Activity位於棧頂,則複用之,不會再new一個實例。此時待啓動Activity的onNewIntent方法會被調用。
若待啓動Activity不在棧頂,則仍是會建立一個它的實例。
(3)singleTask:棧內複用模式
只要Activity已存在於「它想在的棧」中,就複用這個棧中已存在的Activity實例,而不會建立新實例。經過爲Activity指定TaskAffinity屬性可指定它想在的棧,默認爲應用包名。TaskAffinity屬性主要和singleTask啓動模式或是allowTaskReparenting屬性配對使用。若Activity在它想在的棧中,此時待啓動Activity的onNewIntent方法會被調用。
當咱們啓動一個singleTask模式的Activity時,系統會先查找是否存在待啓動Activity想在的棧,如有的話,則看那個棧中是否有它的實例,如有則把這個實例調整到棧頂並調用其onNewIntent方法;若實例不存在,則建立一個該Activity實例並放入棧中。若找不到想在的棧則新建一個棧,再建立一個待啓動Activity的實例並放進去。
singleTask自帶clearTop效果:若待啓動的Activity位於它想在的棧中(但不在棧頂),則系統會把它上面的Activity所有出棧,讓待啓動Activity的實例「提高」到棧頂。
(4)singleInstance:單實例模式
這是一種增強的singleTask模式。它除了具備singleTask的全部特性外,還增強了一點:具備此種模式的Activity所在的任務棧中只能有它一個Activity。系統老是會爲以singleInstance模式啓動的Activity建立一個新的任務棧,再建立一個它的實例放進去。
最後咱們介紹一下allowTaskReparenting屬性:當App A啓動了App B的某個Activity後,若被啓動Activity的allowTaskReparenting屬性爲true,那麼當App B被啓動後,此Activity會直接從應用A的任務棧轉移到應用B的任務棧。由於實際上App B中的Activity的TaskAffinity屬性爲App B的包名,因此它本應屬於B的任務棧,但App B此時未啓動,因此它暫時在A的任務棧中待着。當咱們一旦把相應Activity的allowTaskReparenting屬性設爲true時,待到時機成熟(App B被啓動),這個Activity就會去本該屬於它的地方。
(1)Android Developer
(2)《Android開發藝術探索》