天天看點

Android筆記(一) | Activity的生命周期

下文将分兩部分來讨論Activity的生命周期,參照任玉剛老師的《Android開發藝術探索》一書,結合所學進行總結擴充。
  • 典型情況下的生命周期
  • 異常情況下的生命周期

下圖表示正常情況下Activity的生命周期過程。

Android筆記(一) | Activity的生命周期

image.png

下面是7個生命周期:

/* onCreate:
     * 表示Activity正在被建立,執行一些初始化工作
     * (如:調用 setContentView 加載界面布局資源,初始化Activity所需資料等);
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    /* onStart:
     * 表示Activity正在被啟動,這時Activity已經可見(對應用可見),
     * 隻不過還在背景,使用者還看不到;
     */
    @Override
    protected void onStart() {
        super.onStart();
    }
    /* onResume:
     * 表示Activity已經出現在前台,使用者可見;
     */
    @Override
    protected void onResume() {
        super.onResume();
    }
    /* onPause:
     * 表示Activity正在停止,可以執行存儲資料、停止動畫等不太耗時的工作
     * (因為新活動的onCreate方法要在舊活動的onPause執行完才執行,
     *  為了不影響使用者體驗,要求這個過程盡可能在很短時間内完成);
     */
    @Override
    protected void onPause() {
        super.onPause();
    }
    /* onStop:
     * 表示Activity即将停止,可以做一些稍微重量級的工作,同樣不能太耗時;
     */
    @Override
    protected void onStop() {
        super.onStop();
    }
    /* onDestory:
     * 表示Activity即将被銷毀,執行回收工作和資源釋放。
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    /* onRestart:
     * 表示Activity正在重新啟動,
     * 執行順序為:onPause → onStop → onRestart → onStart → onResume
     */
    @Override
    protected void onRestart() {
        super.onRestart();
    }
           

 上面描述的是Activity正常情況下的生命周期,這裡再結合我們平常使用手機過程中的一些操作,具體說明一下其生命周期過程:

  1. 初次啟動一個Activity,回調情況:
    Android筆記(一) | Activity的生命周期
  2. 從Activity A 打開新的Activity B,B活動回調情況:onPause -> ( Activity B 啟動)-> onStop 。這裡還有一種特殊情況,當新啟動的Activity采用透明主題時,目前Actvity不會回調onStop方法。(見補充說明1)
  3. 從A活動切換到B活動,再回到A活動,期間A活動沒有調用finish()方法。A活動回調情況:
    Android筆記(一) | Activity的生命周期
  4. 按back鍵退出Activity A,A活動回調情況:(見補充說明2)
    Android筆記(一) | Activity的生命周期
  5. 息屏,然後亮屏,回調情況:
    Android筆記(一) | Activity的生命周期

 實踐出真知,這些過程都可以自己寫個簡單的Demo驗證一下,印象更深刻一些。

補充說明:

  1. onStart 和 onStop,onResume 和 onPause 這兩個配對的回調是具有不同意義的,onStart 和 onStop 是從Activity是否可見這個角度來回調的,而onResume 和 onPause則是從Activity是否位于前台來回調的,在實際使用過程中沒有其他明顯差別。說明:onStart(背景可見)-> onResume(前台可見)-> onPause(背景可見)-> onStop(背景也不可見)。

個人觀點:上述執行個體2的原因是在回調onStop方法前,Activity A在背景是可見的,隻不過不在前台無法與使用者發生互動,如果回調了onStop,背景的Activity A也不可見了,那麼Activity B的透明背景之後是預設的白色背景,視覺上會顯得十分尴尬,個人覺得這麼設計也是為了優化使用者體驗吧。

  1. 預設情況下,按back鍵,會回調Activity的 onDestroy 方法,銷毀目前執行個體。
  2. 從Activity A跳轉到 Activity B的過程中,先回調 A 的onPause方法,然後建立Activity B,然後才回調 A 的 onStop 方法(在上面的2,3兩個執行個體中都能發現),是以,不要在onPause方法中執行耗時的操作,以盡快啟動Activity B,使得使用者擁有流暢的使用體驗。

根據手機使用過程中的常見情形,我們從兩種情況來讨論Activity在異常模式下的生命周期:

情況1: 資源相關的系統配置發生改變導緻Activity被殺死并重新建立

  最常見的情形就是手機螢幕發生旋轉時,由于系統配置發生改變,在預設情況下(即沒有特殊設定),Activity會被銷毀并重新建立。其生命周期如下圖:

Android筆記(一) | Activity的生命周期
Android筆記(一) | Activity的生命周期

  與正常生命周期相比,多了資料的儲存和恢複這兩個過程。當Activity在異常情況下終止時,系統會調用onSaveInstanceState方法将Activity的狀态儲存為一個Bundle對象,這個對象會在Activity重新建立後傳遞給onRestoreInstanceState方法和onCreate方法,這個方法的調用時機是在onStop之前,與onPause沒有既定的時序關系。當Activity被重新建立後,系統會調用onRestoreInstanceState,将onSaveInstanceState方法儲存的Bundle對象作為參數,取出其中的資料進行恢複,這個方法的調用時機是在onStart之後。根據這一點,我們可以判斷onRestoreInstanceState方法是否被調用或者onCreate方法中的Bundle參數是否為null來确定Activity是否被重建。

  每個View都有自己的onSaveInstanceState方法和onRestoreInstanceState方法,以根據不同View的需求來恢複不同的資料,例如:TextView恢複了自身文本的選中狀态和文本内容。

  前面提到,onSaveInstanceState方法儲存的資料會傳遞給onRestoreInstanceState方法和onCreate方法,也就是說,進行資料恢複時,有兩種方式,一種是在onCreate方法中進行,一種是在onRestoreInstanceState方法中進行。但是在onCreate方法中進行資料恢複的話,需要考慮Activity是正常啟動的還是被重建的,如果是正常啟動,那麼onCreate(Bundle onSaveInstanceState)中的onSaveInstanceState參數是null。當然,官方文檔是建議采用onRestoreInstanceState方法來恢複資料的。

  前面強調了在預設情況下,系統配置發生改變時,Activity會被重新建立,也就是說,這是可以改變的。我們知道,在AndroidManifest檔案中會對每個Activity進行注冊,而在Activity标簽下有android:configChanges這個屬性。這個屬性下包含很多值,與一些系統配置相對應,當我們希望在某個系統配置改變時不重建這個Activity,就可以在configChanges屬性中添加對應的值。

常用的有:

 1.orientation:螢幕方向發生改變,比如手機螢幕旋轉;

 2.locale:裝置的本地位置發生了改變,一般指切換了系統語言;

 3.keyboardHidden:鍵盤的可通路性發生了改變,例如使用者調出了鍵盤。

<activity android:name=".MainActivity"
    android:configChanges="orientation|locale|keyboardHidden">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
           

補充:

 1. 當我們指定了configChanges屬性時,如果指定的系統配置發生改變,不會重建Activity,但是會調用Activity的 onConfigurationChanged 方法,我們可以根據自己的需求重寫這個函數。

情況2:資源記憶體不足導緻低優先級的Activity被殺死

這種情況不友善模拟,但生命周期和情況1是相同的。Activity的優先級由高到低如下:

 1.前台Activity;

 2.可見但非背景Activity——例如被Dialog遮擋的的Activity;

 3.背景Activity——執行了onStop的Activity。

  如果一個程序中沒有四大元件在執行,那麼這個程序将很快被殺死,是以,一些背景工作最好是放在Service中進而提高優先級,不至于輕易被系統殺死。

下一篇:

Android筆記 | Activity的啟動模式

繼續閱讀