Google Doc: https://developer.android.google.cn/guide/components/activities/
一、Activity生命周期

- 當Activity啟動時,依次會調用onCreate、onStart、onResume。
- 當Activity退居后臺時(不可見,點擊Home或者被新的Activity完全覆蓋),onPause、onStop會依次被調用。
- 當Activity重新回到前臺(從桌面回到原Activity或者被覆蓋后又回到原Activity)時,onRestart、onStart、onResume會依次被調用。
- 當Activity退出銷毀時(點擊back鍵),onPause、onStop、onDestroy會依次被調用。
- 退出當前Activity時–>onPause()–>onStop()–>onDestroy()依次被調用。
當一個 Activity 啟動另一個 Activity 時,第一個 Activity 暫停并停止(但如果它在后臺仍然可見,則不會停止)時,同時系統(tǒng)會創(chuàng)建另一個 Activity,在創(chuàng)建第二個 Activity 前,第一個 Activity 不會完全停止。更確切地說,啟動第二個 Activity 的過程與停止第一個 Activity 的過程存在重疊。
當 Activity A 啟動 Activity B 時:
- Activity A 的
onPause()方法執(zhí)行。 - Activity B 的
onCreate()、onStart()、onResume()方法依次執(zhí)行。(Activity B 現在具有用戶焦點。) - 然后,如果 Activity A 在屏幕上不再可見,則其
onStop()方法執(zhí)行。
此時在Activity B中按下Back鍵,則:
- B.onPause()->A.onRestart->A.onStart->A.onResume-> B.onStop->B.onDestroy。
二、Activity異常生命周期
1 相關系統(tǒng)配置改變導致Activity被殺死并重新創(chuàng)建(一般指橫豎屏切換)
- 豎屏調整為橫屏,則onPause,onSaveInstanceState,onStop,onDestroy,onCreate,onStart,onRestoreInstanceState,onResume依次被調用;
- onSaveInstanceState和onRestoreInstanceState只有在Activity異常終止時才會被調用的,正常情況是不會調用這兩個方法的;
- 在onSaveInstanceState方法和onRestoreInstanceState方法中,系統(tǒng)會自動幫我們恢復一定的數據,如當前Activity的視圖結構、文本框的數據、ListView的滾動位置等,這些View相關的狀態(tài)系統(tǒng)都會幫我們恢復,因為每個View也有onSaveInstanceState方法和onRestoreInstanceState方法

2 內存不足導致低優(yōu)先級的Activity被殺死
當系統(tǒng)內存不足的時候,系統(tǒng)就會按照一定的優(yōu)先級去殺死目標Acitivity的進程來回收內存,并且此時Activity的onSaveInstanceState方法會被調用來存儲數據,并在后續(xù)Activity恢復時調用onRestoreInstanceState方法來恢復數據
三、Activity銷毀重建
當系統(tǒng)配置發(fā)生變化后,Activity會被重建。
如果不想Activity在屏幕旋轉后導致銷毀重建時,可以設置configChange=“orientation”;當SDK版本大于13時,還需額外添加一個“screenSize”的值。
設置了這兩個參數后,當橫豎屏切換時,Activity不會再重建并且也不會調用onSaveInstanceState方法和onRestoreInstanceState方法,而是會回調onConfigurationChanged方法。
四、Activity通信
通過將數據封裝在Bundle對象中 ,然后在Intent跳轉的時候攜帶Bundle對象
該方法可以傳遞基本數據類型和String類型的數據,如果傳遞的是對象就需要進行序列化。類靜態(tài)變量
通過public static定義Activity的靜態(tài)變量然后在其他Activity使用類名.變量名傳遞。Application
通過在Application 中的全局靜態(tài)變量來實現。EventBus
當傳輸的數據量較大的時候Parcelable雖然很便捷,但是會出現異常TransactionTooLargeException。此時可以用插件EventBus。
EventBus 使用的是發(fā)布-訂閱者模型,發(fā)布者通過EventBus發(fā)布事件,訂閱者通過EventBus訂閱事件。當發(fā)布者發(fā)布事件時,訂閱該事件的訂閱者的事件處理方法將被調用。
五、Activity啟動模式
Activity啟動模式分四種:Standard 標準模式,SingleTop 棧頂復用模式、SingleTask 棧內復用模式、SingleInstance 單實例模式。
1 Standard 標準模式
每次啟動一個Activity,都會又一次創(chuàng)建一個新的實例入棧,無論這個實例是否存在。
生命周期:
每次被創(chuàng)建的實例Activity的生命周期符合典型情況,它的onCreate、onStart、onResume都會被調用。
舉例:
Activity棧中已有A、B、C三個Activity,C處于棧頂。若從C Acticity跳轉到另一個C Activity,結果是新建一個C Activity入棧,成為棧頂。

2 SingleTop 棧頂復用模式
- 情況1:若需要創(chuàng)建的Activity已處于棧頂,此時會直接復用棧頂的Activity,不會再創(chuàng)建新的Activity;
- 情況2:若需要創(chuàng)建的Activity不處于棧頂,此時會又一次新建一個新Activity入棧,同Standard模式。
生命周期:
情況1下,棧頂Activity直接被復用,它的onCreate、onStart不會被調用,因為它并沒有發(fā)生改變,但onNewIntent會被調用(Activity被正常創(chuàng)建時不會回調此方法)。
舉例:
Activity棧中已有A、B、C三個Activity,C處于棧頂。情況一:從C跳轉到另一個C,結果是直接復用棧頂的C,不再新建;情況二:從C跳轉到A,結果是新建一個A入棧,成為棧頂。

使用場景:
假設在當前的Activity中要啟動同類型的Activity,此時建議將該Activity指定為SingleTop模式,能夠降低Activity的創(chuàng)建,節(jié)省內存。
3 SingleTask 棧內復用模式
若需要創(chuàng)建的Activity已處于棧中,不會再新建Activity,而是將存在棧中的Activity上面的其他所有Activity銷毀,使它成為棧頂。
生命周期:
同SingleTop情況一同樣,僅會回調Activity的onNewIntent方法。
舉例:
Activity棧中已有A、B、C三個Activity,C處于棧頂。情況一:從C跳轉到C,則直接復用棧頂的C;情況二:從C跳轉到A,則將A上面的B、C銷毀,使A成為棧頂。

使用場景:
最常見的應用場景就是保持應用開啟后僅僅有一個Activity的實例。
比如:應用中展示的主頁,假設用戶在主頁跳轉到其他頁面,多次操作后想返回到主頁,假設不使用SingleTask模式,在點擊返回的過程中會多次看到主頁,不合理。
4 SingleInstance 單實例模式
全局單例模式,加強的SingleTask。具有此模式的Activity僅僅能單獨位于一個任務棧中。經常適用于系統(tǒng)中的應用,比如Launch、鎖屏鍵的應用等,整個系統(tǒng)中僅有一個。
舉例:
A Activity是該模式,啟動A后,系統(tǒng)會為它創(chuàng)建一個單獨的任務棧,由于棧內復用的特性,新的請求均不會創(chuàng)建新的Activity,除非這個獨特的任務棧被系統(tǒng)銷毀。
六、使用方式
使用方法有兩種:
- AndroidManifest.xml中為Activity指定launchMode。
- 動態(tài)指定,通過Intent的addFlags方法動態(tài)指定啟動模式。
優(yōu)先級:
第2種比第1種優(yōu)先級高,若兩者同時存在,以2為準
限定范圍:
第1種無法為Activity直接指定FLAG_ACTIVITY_CLEAR_TOP標識;
第2種無法為Activity指定SingleInstance模式。
注意:須考慮Activity跳轉時攜帶頁面參數的問題
當一個Activity設置了SingleTop或者SingleTask模式后,跳轉此Activity出現復用原有Activity的情況時,此Activity的onCreate方法將不會再調用。onCreate方法僅會在第一次創(chuàng)建Activity時被調用。
而一般onCreate方法中會進行該頁面的數據初始化、UI初始化,假設頁面的展示數據無關頁面跳轉傳遞的參數,則不必操心此問題;若頁面展示的數據就是通過getIntent() 方法來獲取,那么問題就會出現:getIntent()獲取的一直都是老數據,根本無法接收跳轉時傳送的新數據!
這時我們需要另外一個回調 onNewIntent(Intent intent)方法。此方法會傳入最新的intent,這樣我們就能夠解決上述問題。這里建議的方法是再次調用setIntent。然后重新初始化數據和UI。
七、相關Flags
1 FLAG_ACTIVITY_NEW_TASK
為Activity指定SingleTask啟動模式,與AndroidManifest.xml指定效果相同。
2 FLAG_ACTIVITY_SINGLE_TOP
為Activity指定SingleTop啟動模式,與AndroidManifest.xml指定效果相同。
3 FLAG_ACTIVITY_CLEAN_TOP
具有此標記的Activity,啟動時會將與其同棧的其他Activity出棧。一般與SingleTask啟動模式一起出現。它會完畢SingleTask的作用,但事實上SingleTask啟動模式默認具有此標記的作用。
4 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此標記的Activity不會出現在Activity列表中。
使用場景:某些情況下不希望用戶通過歷史列表回到某個Activity時,此標記便可以實現該效果。
等同于AndroidManifest.xml中指定Activity屬性:android:excludeFromRecents="true"
八、監(jiān)聽Activity生命周期
在Application中調用 registerActivityLifecycleCallbacks(),通過 ActivityLifecycleCallbacks 接口的實現,完成對Activity各個生命周期信息的采集。
比如哪個Activity在什么時間處于onCreate、onStop等等,進而統(tǒng)計出Activity的使用時間和使用次數。