Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Activity生命周期詳解

Activity生命周期詳解

編輯:關於Android編程

 分析android Activity啟動流程中ActivityManagerService所扮演的角色

一、概述

上一篇文章startActivity啟動過程分析,介紹了startActivity是如何一步步創建的,再來看看生命周期的控制。先來一張官方的Activity狀態轉換圖:

activity_lifecycle

Activity的生命周期中只有在以下3種狀態之一,才能較長時間內保持狀態不變。

  • Resumed(運行狀態):Activity處於前台,且用戶可以與其交互。
  • Paused(暫停狀態): Activity被在前台中處於半透明狀態或者未覆蓋全屏的其他Activity部分遮擋。 暫停的Activity不會接收用戶輸入,也無法執行任何代碼。
  • Stopped(停止狀態):Activity被完全隱藏,且對用戶不可見;被視為後台Activity。 停止的Activity實例及其諸如成員變量等所有狀態信息將保留,但它無法執行任何代碼。

除此之外,其他狀態都是過渡狀態(或稱為暫時狀態),比如onCreate(),onStart()後很快就會調用onResume()方法。

二. 生命周期

2.1 進程間通信

對於App來說,其Activity的生命周期執行是與系統進程中的ActivityManagerService有一定關系的,接下來從進程和線程的角度來分析Activity的生命周期,這裡涉及到系統進程和應用進程:

system_server進程是系統進程,Java framework框架的核心載體,裡面運行了大量的系統服務,比如這裡提供ApplicationThreadProxy(簡稱ATP),ActivityManagerService(簡稱AMS),這個兩個服務都運行在system_server進程的不同線程中,由於ATP和AMS都是基於IBinder接口,都是binder線程,binder線程的創建與銷毀都是由binder驅動來決定的。

App進程是應用程序所在進程,主線程主要負責Activity/Service等組件的生命周期以及UI相關操作都運行在這個線程; 另外,每個App進程中至少會有兩個binder線程 ApplicationThread(簡稱AT)和ActivityManagerProxy(簡稱AMP),除了下圖中所示的線程,其實還有很多線程,比如signal catcher線程等。

app_process

Binder用於不同進程之間通信,由一個進程的Binder客戶端向另一個進程的服務端發送事件,比如圖中線程2向線程4發送事務;而handler用於同一個進程中不同線程的通信,比如圖中線程4向主線程發送消息。

結合圖說說Activity生命周期,比如暫停Activity的流程如下:

  • 線程1的AMS中調用線程2的ATP來發送事件;(由於同一個進程的線程間資源共享,可以相互直接調用,但需要注意多線程並發問題)
  • 線程2通過binder將暫停Activity的事件傳輸到App進程的線程4
  • 線程4通過handler消息機制,將暫停Activity的消息發送給主線程
  • 主線程在looper.loop()中循環遍歷消息,當收到暫停Activity的消息(PAUSE_ACTIVITY)時,便將消息分發給ActivityThread.H.handleMessage()方法,再經過方法的層層調用,最後便會調用到Activity.onPause()方法。

這便是由AMS完成了onPause()控制,那麼同理Activity的其他生命周期也是這麼個流程來進行控制的。

2.2 App主線程

每個App都有一個主線程,大家常說主線程是ActivityThread,其實這個說法是欠妥當的,首先何為線程?一般來說Java層創建線程往往是繼承Thread對象或者實現Runnable,再看看ActivityThread,會發現該對象並沒有繼承任何對象。准確說法ActivityThread是運行在主線程的對象,充當著主線程的職責。

那主線程到底是哪個呢,這個問題涉及到Linux進程與線程的理解,本質上來說大家常說的主線程就是app首次啟動時創建的進程,對於Linux來說進程與線程都是一個task_struct結構體,除了是否有獨立資源,並沒有什麼區別。

那有為何說充當著主線程的職責呢?這是由於進程在創建之初會為主線程創建Looper對象,這個便是用來維護Activity的生命周期。關於更多詳細,可查看我之前在知乎 的一個回答Android中為什麼主線程不會因為Looper.loop()裡的死循環卡死?

2.3 樞紐中心

Activity的生命周期,都是其他線程通過handler發送消息給主線程,那麼主線程中的ActivityThread的內部類H控制整個核心消息處理機制,通過H.handleMessage()來控制Activity的生命周期,在H類中共定義了50種消息。

private class H extends Handler {
  public static final int LAUNCH_ACTIVITY         = 100;
  public static final int PAUSE_ACTIVITY          = 101;
  public static final int PAUSE_ACTIVITY_FINISHING= 102;
  public static final int STOP_ACTIVITY_SHOW      = 103;
  public static final int STOP_ACTIVITY_HIDE      = 104;
  public static final int SHOW_WINDOW             = 105;
  public static final int HIDE_WINDOW             = 106;
  public static final int RESUME_ACTIVITY         = 107;
  public static final int SEND_RESULT             = 108;
  public static final int DESTROY_ACTIVITY        = 109;
  public static final int BIND_APPLICATION        = 110;
  public static final int EXIT_APPLICATION        = 111;
  public static final int NEW_INTENT              = 112;
  public static final int RECEIVER                = 113;
  public static final int CREATE_SERVICE          = 114;
  public static final int SERVICE_ARGS            = 115;
  public static final int STOP_SERVICE            = 116;

  public static final int CONFIGURATION_CHANGED   = 118;
  public static final int CLEAN_UP_CONTEXT        = 119;
  public static final int GC_WHEN_IDLE            = 120;
  public static final int BIND_SERVICE            = 121;
  public static final int UNBIND_SERVICE          = 122;
  public static final int DUMP_SERVICE            = 123;
  public static final int LOW_MEMORY              = 124;
  public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
  public static final int RELAUNCH_ACTIVITY       = 126;
  public static final int PROFILER_CONTROL        = 127;
  public static final int CREATE_BACKUP_AGENT     = 128;
  public static final int DESTROY_BACKUP_AGENT    = 129;
  public static final int SUICIDE                 = 130;
  public static final int REMOVE_PROVIDER         = 131;
  public static final int ENABLE_JIT              = 132;
  public static final int DISPATCH_PACKAGE_BROADCAST = 133;
  public static final int SCHEDULE_CRASH          = 134;
  public static final int DUMP_HEAP               = 135;
  public static final int DUMP_ACTIVITY           = 136;
  public static final int SLEEPING                = 137;
  public static final int SET_CORE_SETTINGS       = 138;
  public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
  public static final int TRIM_MEMORY             = 140;
  public static final int DUMP_PROVIDER           = 141;
  public static final int UNSTABLE_PROVIDER_DIED  = 142;
  public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
  public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
  public static final int INSTALL_PROVIDER        = 145;
  public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
  public static final int CANCEL_VISIBLE_BEHIND = 147;
  public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
  public static final int ENTER_ANIMATION_COMPLETE = 149;
}

主線程每到收到其他線程發送過來的不同的Handler消息,則都會觸發相應的H.handleMessage,下面列舉跟Activity相關的一些常見消息。

  • LAUNCH_ACTIVITY
  • RELAUNCH_ACTIVITY
  • RESUME_ACTIVITY
  • NEW_INTENT
  • PAUSE_ACTIVITY / PAUSE_ACTIVITY_FINISHING
  • STOP_ACTIVITY_SHOW / STOP_ACTIVITY_HIDE
  • DESTROY_ACTIVITY

一般來說收到消息,都會調用相應handlerxxx方法。比如,LAUNCH_ACTIVITY則對應handleLaunchActivity, RESUME_ACTIVITY則對應handleResumeActivity等。

public void handleMessage(Message msg) {
  switch (msg.what) {
    case LAUNCH_ACTIVITY: {
        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
        r.packageInfo = getPackageInfoNoCheck(
                r.activityInfo.applicationInfo, r.compatInfo);
        handleLaunchActivity(r, null);
    } break;
    case RELAUNCH_ACTIVITY: {
        ActivityClientRecord r = (ActivityClientRecord)msg.obj;
        handleRelaunchActivity(r);
    } break;
    case PAUSE_ACTIVITY:
        handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                (msg.arg1&2) != 0);
        maybeSnapshot();
        break;
    case STOP_ACTIVITY_SHOW:
        handleStopActivity((IBinder)msg.obj, true, msg.arg2);
        break;
    case STOP_ACTIVITY_HIDE:
        handleStopActivity((IBinder)msg.obj, false, msg.arg2);
        break;
    case RESUME_ACTIVITY:
        handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
        break;
    case DESTROY_ACTIVITY:
            handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
                    msg.arg2, false);
            break;
     ...
  }
}

先簡單列舉先調用鏈可能涉及的方法(注:並非每次都能同時進入如下調用鏈的每個分支,先大致列舉,後續再展開)

三. 調用鏈

3.1 啟動應用

消息: LAUNCH_ACTIVITY

調用鏈

ActivityThread.handleLaunchActivity
    ActivityThread.handleConfigurationChanged
        ActivityThread.performConfigurationChanged
            ComponentCallbacks2.onConfigurationChanged

    ActivityThread.performLaunchActivity
        LoadedApk.makeApplication
            Instrumentation.callApplicationOnCreate
                Application.onCreate

        Instrumentation.callActivityOnCreate
            Activity.performCreate
                Activity.onCreate

        Instrumentation.callActivityonRestoreInstanceState
            Activity.performRestoreInstanceState
                Activity.onRestoreInstanceState

    ActivityThread.handleResumeActivity
        ActivityThread.performResumeActivity
            Activity.performResume
                Activity.performRestart
                    Instrumentation.callActivityOnRestart
                        Activity.onRestart

                    Activity.performStart
                        Instrumentation.callActivityOnStart
                            Activity.onStart

                Instrumentation.callActivityOnResume
                    Activity.onResume

采用縮進方式,來代表方法的調用鏈,相同縮進層的方法代表來自位於同一個調用方法裡。callActivityOnCreate和callActivityonRestoreInstanceState相同層級,代表都是由上一層級的ActivityThread.performLaunchActivity()方法中調用。

App角度

調用鏈過程層層調用,但對上層應用是透明的,App開發者只需要覆寫其中重要的回調函數即可,故此處所說的App角度,便是指App開發者來說可見之處。經過上述的調用鏈,依次會執行下面回調方法。

  1. ComponentCallbacks2.onConfigurationChanged():
  2. Application.onCreate()
  3. Activity.onCreate()
  4. Activity.onRestoreInstanceState()
  5. Activity.onRestart()
  6. Activity.onStart()
  7. Activity.onResume()

Application和Activity都實現了ComponentCallbacks2接口;所以Application和Activity會先執行onConfigurationChanged()回調方法。在前面說過onCreate()是過渡狀態,緊跟著會執行handleResumeActivity()方法,然後就進入Resumed狀態。

3.2 恢復應用

消息: RESUME_ACTIVITY

調用鏈

ActivityThread.handleResumeActivity
    ActivityThread.performResumeActivity
        Activity.performResume
            Activity.performRestart
                Instrumentation.callActivityOnRestart
                    Activity.onRestart

                Activity.performStart
                    Instrumentation.callActivityOnStart
                        Activity.onStart

            Instrumentation.callActivityOnResume
                Activity.onResume

App角度

  1. Activity.onRestart()
  2. Activity.onStart()
  3. Activity.onResume()

App處於運行狀態,UI可見。

3.3 暫停應用

msg: PAUSE_ACTIVITY

調用鏈

ActivityThread.handlePauseActivity
    ActivityThread.performPauseActivity
        ActivityThread.callCallActivityOnSaveInstanceState
            Instrumentation.callActivityOnSaveInstanceState
                Activity.performSaveInstanceState
                    Activity.onSaveInstanceState

        Instrumentation.callActivityOnPause
            Activity.performPause
                Activity.onPause

App角度

  1. Activity.onSaveInstanceState()
  2. Activity.onPause()

根據saveState是否true決定是否執行callCallActivityOnSaveInstanceState()分支,從而決定是否回調onRestoreInstanceState()方法

3.4 停止應用

msg: STOP_ACTIVITY_HIDE

調用鏈

ActivityThread.handleStopActivity
    ActivityThread.performStopActivityInner
        ActivityThread.callCallActivityOnSaveInstanceState
            Instrumentation.callActivityOnSaveInstanceState
                Activity.performSaveInstanceState
                    Activity.onSaveInstanceState

        ActivityThread.performStop
            Activity.performStop
                Instrumentation.callActivityOnStop
                    Activity.onStop

    updateVisibility

    H.post(StopInfo)
        AMP.activityStopped
            AMS.activityStopped
                ActivityStack.activityStoppedLocked
                AMS.trimApplications
                    ProcessRecord.kill
                    ApplicationThread.scheduleExit
                        Looper.myLooper().quit()

                    AMS.cleanUpApplicationRecordLocked
                    AMS.updateOomAdjLocked

App角度

  1. Activity.onSaveInstanceState
  2. Activity.onStop

在停止Activity的過程,會有一個trimApplications()的操作,主要是kill空進程,將當前進程退出loop循環,清理應用的上下文環境,並且更新進程的Adj值。

3.5 銷毀應用

msg: DESTROY_ACTIVITY

調用鏈

ActivityThread.handleDestroyActivity
    ActivityThread.performDestroyActivity
        Instrumentation.callActivityOnPause
        Activity.performStop()
        Instrumentation.callActivityOnDestroy
            Activity.performDestroy
                Window.destroy
                Activity.onDestroy

    AMP.activityDestroyed
        AMS.activityDestroyed
            ActivityStack.activityDestroyedLocked
                ActivityStackSupervisor.resumeTopActivitiesLocked
                    ActivityStack.resumeTopActivityLocked
                        ActivityStack.resumeTopActivityInnerLocked

App角度

  • Activity.onDestroy

銷毀應用後,會查看第一個沒有結束的Activity,用於顯示在最頂層界面,當不存在未結束的Activity時,則顯示Launcher界面,即主界面。

3.6 創建Intent

msg: NEW_INTENT (打開已經處於棧頂的Activity,則會發送給NEW_INTENT消息給主線程)

調用鏈

ActivityThread.handleNewIntent
    performNewIntents
        Instrumentation.callActivityOnPause
            Activity.performPause
                Activity.onPause

        deliverNewIntents
            Instrumentation.callActivityOnNewIntent
                Activity.onNewIntent

        Activity.performResume
            Activity.performRestart
                Instrumentation.callActivityOnRestart
                    Activity.onRestart

                Activity.performStart
                    Instrumentation.callActivityOnStart
                        Activity.onStart

            Instrumentation.callActivityOnResume
                Activity.onResume

App角度

  1. Activity.onPause
  2. Activity.onNewIntent
  3. Activity.onRestart
  4. Activity.onStart
  5. Activity.onResume

本文主要是概括性講述Activity的調用過程,後續會再從源碼角度進一步細說Activity生命周期,敬請期待。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved