深刻Android系統(十一)AMS-2-Activity生命週期管理

Activity管理

Activity是最複雜的一個組件,它負責UI的顯示以及處理各類輸入事件。Activity提供窗口供應用在其中繪製界面,同時也提供了各類各樣的控件方便開發。Activity 官網傳送門前端

另外,Android中並無對外提供啓動進程的接口,只是在啓動ActivityService時,由系統根據須要來啓動進程。java

Activity的生命週期

關於Activity的生命週期,咱們先看下官方圖示:
imageandroid

Activity的生命週期圖中隱含了Activity運行時的三種狀態,分別是:瀏覽器

  • 激活態:新啓動的Activity位於屏幕的最前端,能夠接受用戶輸入的狀態
  • 暫停態:當Activity被一個透明或半透明的Activity覆蓋,此時Activity雖然不能接收用戶的輸入,但仍是可見的
  • 中止態:當一個Activity徹底被另外一Activity覆蓋,不能接受用戶輸入也不可見時

當一個Activity對象的狀態發生變化時,會調用上圖中定義的抽象接口來通知應用。相關描述以下:markdown

  • onCreate():當Activity對象被建立時調用
  • onStart():當ActivityFramework中的數據結構準備完畢後調用
  • onResume():當Activity來到棧的最前端變成激活態時調用
  • onPause():當Activity從棧的最前端切換到後臺時,進入暫停態,並調用該方法
  • onStop():當Activity已經徹底不可見時調用
  • onDestroy():在銷燬Activity前,系統會先調用該方法

上面的知識在初學Android時咱們就已經知道了,接下來咱們要從AMS的角度看下這幾個方法是如何調用的,不過在此以前咱們先熟悉下另外的幾個相關知識:IntentTaskLaunchMode網絡

IntentTaskLaunchMode

理解Intent

Intent是所請求執行動做的抽象描述,一般做爲參數來使用,用於完成各個組件之間的消息傳遞。更爲詳細的姿式能夠參考官網描述:官網傳送門數據結構

Intent類的相關定義以下:app

public class Intent implements Parcelable, Cloneable {
    private String mAction;
    private Uri mData;
    private String mType;
    private String mPackage;
    private ComponentName mComponent;
    private int mFlags;
    private ArraySet<String> mCategories;
    private Bundle mExtras;
    private Rect mSourceBounds;
    private Intent mSelector;
    private ClipData mClipData;
}
複製代碼

經常使用字段含義以下:ide

  • mAction是一個字符串,用來指明要執行的操做是什麼。
    • Intent類中定義了大量的Action,例如ACTION_VIEWACTION_SEND等。
    • 這些Action的做用與具體的功能模塊相關,表達要執行的意圖
  • mData儲存須要傳遞的數據,類型是URI
    • URI是統一資源標識符(Uniform Resources Identifier)的簡稱
    • 最初用於表示Web中的各類資源,如HTML文檔、圖片、文件等
    • URL(Uniform Resource Locator)URI的一種
  • mTypeMIME格式的字符串,表示數據類型。
    • MIME是多功能Internet郵件擴充服務(Multipurpose Internet Mail Extensions)的縮寫
    • 最先英語電子郵件系統,後來應用到瀏覽器。格式例如:text/plain``application/x-gzip
    • 一般該數據類型不須要指定,若是設置了這個字段,能夠加快Intent的匹配速度
  • mComponent用於指定接收Intent的目標組件的名稱
    • mComponent的類型是ComponentName,它包含兩個字符串:mPackagemClass,前者用於指定包名,後者用於指定類名
    • Intent中若是定義了mComponent,該Intent將直接發送到指定的組件,不會在經過其餘屬性組合查找
  • mFlags稱爲標誌,在Intent類中定義了不少flag的相關常量。主要分爲兩種
    • FLAG_ACTIVITY_...開頭的,用來控制Activity啓動的相關參數,如FLAG_ACTIVITY_NEW_TASK
    • FLAG_RECEIVER_...開頭的,用來進行廣播的參數
  • mCategories一個包含應處理Intent組件類型的附加信息的字符串。常見的類別有兩種:
    • CATEGORY_BROWSABLE:目標Activity容許自己經過網絡瀏覽器啓動,以顯示連接引用的數據
    • CATEGORY_LAUNCHER:該Activity是任務的初始Activity
    • 能夠將任意數量的類別描述放入一個 Intent中,但大多數Intent均不須要類別
  • mExtras表示全部附加信息的集合。
    • mExtras數據類型是Bundle
    • 可使用各類putExtra()方法添加extra數據,每種方法均接受兩個參數:keyvalue

Task

TaskActivity的集合。Android把用戶一次相關操做中使用的Activity按照前後順序保存在Task中,這樣當按back鍵時就能按照相反的順序回退。函數

Task像一個棧,之後進先出的方式管理着Activity。系統運行時內存中會存在着多個Task,當咱們按recent鍵時,會彈出一個選擇列表,這個列表就是系統中存在的Task的集合,選擇一個Task將把它所包含的Activity做爲一個總體帶到前臺。Task中的Activity的順序一般是不能改變的,只能經過出棧入棧的方式來增長或移除。

AMS中使用ActivityStack來管理Task,它管理的Task都存放在成員變量mTaskHistory中,定義以下:

class ActivityStack{
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
}
複製代碼

mTaskHistory是一個列表,儲存的是TaskRecord對象。TaskRecord對象表示一個Task,它的成員變量mActivities也是一個列表,儲存了該Task中全部的ActivityRecord對象。mActivities的定義以下:

class TaskRecord{
    final ArrayList<ActivityRecord> mActivities;
}
複製代碼

那麼,如何才能開始一個新的Task呢?

  • Intent中定義了一個標誌FLAG_ACTIVITY_NEW_TASK,在startActivity()Intent參數中加入該標誌就能開啓一個新的Task
  • 可是若是系統中已經有相同affinityTask存在,並不會再啓動一個Task,而是將舊的Task帶到前臺

那麼,affinity在哪裏定義的呢?

  • affinity的意思是親和度,是經過<activity>標籤的android:taskAffinity屬性來定義的
  • 當使用標誌FLAG_ACTIVITY_NEW_TASK啓動一個Activity時,這個ActivitytaskAffinity屬性中的字符串就會成爲Taskaffinity
  • 之後加入這個TaskActivity,即便它們的taskAffinity屬性定義了一個不一樣的字符串,也不會改變Task已有的affinity
  • 若是<activity>標籤中沒有指定android:taskAffinity屬性,這個Activity會繼承<application>標籤的android:taskAffinity屬性
  • 若是<application>標籤的android:taskAffinity屬性也沒有定義,將會使用應用包名做爲缺省值
    • 正由於如此,若是在應用中啓動本應用的另外一個Activity,即便使用了FLAG_ACTIVITY_NEW_TASK標誌也不必定會啓動一個新的Task
    • 除非這個Activity定義了不一樣的taskAffinity屬性

LaunchMode

Activity的啓動模式隱含的是Activity對象的複用問題,關於啓動模式官網的介紹也很詳細:官方傳送門

當啓動一個Activity時,若是系統的後臺Task中已經有一個該Activity的實例存在了,系統是建立一個新的Activity仍是將已經存在的Activity切換到前臺呢?

答案是都有可能,有多種因素能夠影響結果。包括Activity的屬性值以及Intent中指定的標誌

咱們先看下Activity的屬性launchMode會有哪些影響:

  • standard模式:默認。
    • standard模式下的Activity每次啓動時都會建立該Activity的實例對象
    • 同一個Task中能夠同時存在該Activity的多個實例
    • 一個Activity的多個實例能夠出如今多個Task棧中
  • singleTop模式
    • 若是目標Task的頂部已存在該Activity實例,則系統會經過調用該實例的onNewIntent()方法向其傳送Intent,而非建立新的Activity實例。
    • 若是不在棧頂,這standard模式同樣建立新的實例對象
  • singleTask模式
    • 設置singleTask模式的Activity具備系統惟一性,只能在系統中建立該Activity的一個實例對象
    • 啓動設置爲singleTask模式的Activity時,若是系統中已經存在該Activity的實例對象,則將其所在的Task中排在它前面的Activity都彈出棧,將該Activity帶到棧頂,並調用其onNewIntent()方法傳遞新的Intent對象
    • 若是系統中不存在該Activity的實例對象,則會建立一個該Activity的實例對象
      • 若是該ActivitytaskAffinity屬性值和當前Taskaffinity值相同,它會加入當前的Task
      • 不然,即便啓動該ActivityIntent中沒有指定FLAG_ACTIVITY_NEW_TASK標誌,也會啓動新的Task,並將Activity至於其中
  • singleInstance模式
    • 設置爲singleInstance模式的Activity一樣具備系統惟一性,系統中只有該Activity的一個實例對象
    • 同時系統不會將任何其餘Activity啓動到包含該Activity實例的Task
    • Activity始終是其Task中的惟一Activity

一般狀況下,一個Activity建立出來後,會停留在某個Task中,直到它被銷燬

  • 可是,若是ActivityallowTaskReparenting屬性設置爲true,該Activity能夠在不一樣的Task之間轉移
  • 不過,這個屬性只有在啓動ActivityIntent中設置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標誌時才起做用

除了上面介紹的內容,ActivityTask的工做邏輯你們能夠參考官網:任務和返回堆棧

好比,下面部分提到的技巧就很重要(摘抄自官網):

只有當 Activity 具備 ACTION_MAIN 和 CATEGORY_LAUNCHER 過濾器時,才應使用 "singleTask" 和 "singleInstance" 這兩種啓動模式,它們會將 Activity 標記爲始終啓動任務。好比,能夠想象一下,若是缺乏該過濾器會發生什麼狀況:intent 會啓動 "singleTask" Activity,隨之啓動新任務,用戶花了一些時間在該任務上。而後,用戶按主屏幕按鈕。此時,該任務會轉到後臺,再也不可見。如今,用戶沒法返回到該任務,由於它未顯示在應用啓動器中。

瞭解ClientTransactionHandler的做用

ClientTransactionHandler是在Android 9.0上出現的,用來串聯起AMSActivity的整個生命週期管理的類,很重要

咱們已經知道應用的入口是ActivityThread類的main()函數,仔細看下類結構的話會發現要ActivityThread繼承了一個特殊的類。定義以下

public final class ActivityThread extends ClientTransactionHandler {
    ...
}
複製代碼

能夠看到ActivityThread繼承了ClientTransactionHandler類。這個類是在Android 9.0加入的,關鍵定義以下:

public abstract class ClientTransactionHandler {
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    ......
    public abstract void handleDestroyActivity(...);
    public abstract void handlePauseActivity(...);
    public abstract void handleResumeActivity(...);
    public abstract void handleStopActivity(...);
    ......
    public abstract Activity handleLaunchActivity(...);
    public abstract void handleStartActivity(...);
    ......
    public abstract void handleNewIntent(...);
    ......
}
複製代碼

類中定義了和聲明週期有關的方法,機智的咱們能夠猜到,AMS後面生命週期的回調控制應該就是經過它來實現的,相關類繼承關係以下:
image

能夠AndroidActivity相關的生命週期要作的事情抽象了出來,在上面定義的類中,真正業務實現包括:

  • LaunchActivityItem就是要執行launch activity任務
  • resume activity則是經過ResumeActivityItem實現
  • pause activity則是經過PauseActivityItem實現
  • stop activity則是經過StopActivityItem實現
  • destroy activity則是經過DestoryActivityItem實現

ClientTransaction的調用邏輯

咱們看下整個調用流程: 在ActivityThread中的ApplicationThread類有一個scheduleTransaction()方法,

ApplicationThread類是一個Binder服務類,AMS會做爲client調用這個服務類,固然也就能夠調用它的scheduleTransaction()方法

scheduleTransaction()方法內容以下:

@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}
複製代碼

調用的是ActivityThreadscheduleTransaction()方法,也就是ClientTransactionHandler類的scheduleTransaction()方法,方法以下:

void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
複製代碼

發送了一個EXECUTE_TRANSACTION消息給ActivityThreadHandler實現類H,消息處理以下:

case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        transaction.recycle();
    }
    break;
複製代碼

消息處理中使用了mTransactionExecutor.execute(),不出意外,執行邏輯確定在TransactionExecutor中了,咱們看下:

public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        executeCallbacks(transaction);
        executeLifecycleState(transaction);
        mPendingActions.clear();
    }
    public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        if (callbacks == null) {
            return;
        }
        ......
        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            ......
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            ......
        }
    }
    private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }
        ......
        // 很重要的一個方法
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
複製代碼

能夠看到,最後分別在executeCallbacks()executeLifecycleState()兩個方中執行了item.execute()lifecycleItem.execute()兩個方法

executeCallbacks()executeLifecycleState()目的分別是幹什麼呢?結合類關係圖咱們能夠這樣推斷:

  • executeCallbacks()遍歷執行的是ClientTransaction類中List<ClientTransactionItem> mActivityCallbacks集合中的元素
    • ClientTransactionItem類的直接子類實現只有LaunchActivityItem
    • 也就是說executeCallbacks()主要執行的是launch activity的通知操做
  • executeLifecycleState()執行的是ClientTransaction類中的ActivityLifecycleItem mLifecycleStateRequest
    • mLifecycleStateRequest被稱爲final state
    • 從繼承關係上能夠看到,resume activitypasue activitystop activitydestory activity都在這裏

瞭解完調用流程會發現,實現類中並無StartActivityItem,爲何呢?那怎麼調用onStart()函數呢?
核心就在cycleToPath()函數身上

TransactionExecutor.cycleToPath()

針對Activity的生命週期,Android並無定義出全部的*ActivityItem類,例如StartActivityItem就並不存在,那麼怎麼去執行這個start階段的函數呢?

請留意類圖中ActivityLifecycleItem有關生命週期的常量定義,Android在這裏經過cycleToPath()採用了一種比較取巧的操做,核心邏輯就是:

  • 指定一個Activityfinal state
  • 根據Activity的當前狀態去計算過程當中須要的狀態,並保存到集合中
  • 最後按順序執行集合中的狀態

以文章後面的realStartActivityLocked()方法爲例

  • LaunchActivityItem類型的對象添加到callback
    • TransactionExecutor會先執行LaunchActivityItem
    • 執行完後Activity進入到ON_CREATE狀態
  • 方法中指定了final stateResumeActivityItem
    • TransactionExecutor經過cycleToPath()計算當前狀態與final state的差別
    • 當前狀態爲ON_CREATE狀態,final stateON_RESUME
    • TransactionExecutor經過幫助類的getLifecyclePath方法將二者之間缺失的狀態整理到集合中
    • 而後調用performLifecycleSequence()循環處理

performLifecycleSequence()方法以下:

private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(...);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(...);
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(...);
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(...);
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(...);
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(...);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }
複製代碼

PauseActivityItem的調用分析

PauseActivityItem類爲例,咱們看看具體的執行邏輯:

public class PauseActivityItem extends ActivityLifecycleItem {
    ......
    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        ......
        client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        ......
    }
}
複製代碼

執行的是ClientTransactionHandler抽象類,其實也就是ActivityThread類的handlePauseActivity()方法。

handlePauseActivity()方法調用了ActivityThread類的performPauseActivity()方法,最後調用到的是performPauseActivityIfNeeded()方法,代碼以下:

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        ......
        mInstrumentation.callActivityOnPause(r.activity);
        ......
    }
複製代碼

執行的是Instrumentation類的callActivityOnPause()方法,內容以下:

public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
複製代碼

很簡潔,繼續查看:

public class Activity{
    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
        mResumed = false;
        ......
    }
}
複製代碼

有木有!有木有!onPause();終於調用到了。。。。。。

咱們已經從應用端找到了調用的流程,可是,對於AMS來講它是怎麼觸發的呢?

接下來,咱們分析下Activity的啓動,在Activity啓動的過程咱們就能夠找到AMS觸發聲明週期的例子

啓動Activity

研究Activity生命週期的調用細節,咱們仍是得從最熟悉的地方入手,也就是經常使用的Activity對象的startActivity (Intent intent)方法

Activty.startActivty()

跟蹤startActivity (Intent intent)方法,發現調用關係以下:

class Activity{
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }
    public void startActivityForResult(...) {
        ......
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
        ......
    }
}
class Instrumentation{
    public ActivityResult execStartActivity(...) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(...);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
}
class ActivityManagerService{
    public final int startActivity(...) {
        return startActivityAsUser(...);
    }
    public final int startActivityAsUser(...) {
        ......
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                ...
                .execute();
    }
}
複製代碼

咱們看到最後是調用的是AMSstartActivityAsUser方法。跟蹤startActivityAsUser方法的調用過程就會發現最後執行的是ActivityStarter類的execute()方法來執行Activity的啓動,相關代碼以下:

class ActivityStater{
    int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(...);
            } else {
                return startActivity(...);
            }
        } finally {
            onExecutionComplete();
        }
    }
}
複製代碼

咱們看到execute()有兩個啓動Activity的方法,接下來咱們以startActivityMayWait()方法繼續分析,由於最後也會走到startActivity()中。

ActivityStarter.startActivityMayWait()

簡要代碼以下:

private int startActivityMayWait(...) {
    ......
    // 獲取要啓動的 Activity 的信息
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    synchronized (mService) {
        ......
        int res = startActivity(caller, ...);
        ......
        if (outResult != null) { // 須要返回結果
            outResult.result = res;
            final ActivityRecord r = outRecord[0];
            switch(res) {
                case START_SUCCESS: {
                    // 添加到特定集合中
                    mSupervisor.mWaitingActivityLaunched.add(outResult);
                    do {
                        try {
                            // 等待應用進程中的 Activity 啓動完成
                            mService.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (outResult.result != START_TASK_TO_FRONT
                            && !outResult.timeout && outResult.who == null);
                    ......
                    break;
                }
                ......
            }
        }
        return res;
    }
}
複製代碼

startActivityMayWait()方法的流程以下:

  • 首先調用resolveActivity()方法來獲取要啓動的Activity的信息
  • 獲得Activity的信息後,繼續調用startActivity()方法來繼續啓動Activity
  • 若是啓動Activity的應用須要獲取返回結果,則調用mService對象的wait()方法掛起線程等待啓動的結果

接下來就是調用ActivityStarterstartActivity()方法的代碼,咱們看下部分細節:

private int startActivity(IApplicationThread caller, ...) {
    int err = ActivityManager.START_SUCCESS;
    ......
    if (caller != null) {
        // 獲取啓動Activity的進程的信息
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    final int userId = aInfo != null && aInfo.applicationInfo != null
            ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
    ......// 省略不少錯誤檢查
    // 檢查調用者的相關權限
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(...);
    // 檢查 Intent 防火牆是否屏蔽了該 Intent
    abort |= !mService.mIntentFirewall.checkStartActivity(...);
    ......
    if (mService.mController != null) {
        try {
            // 將 Activity 啓動的消息通知監聽系統Activity變更的接口 IActivityControler
            Intent watchIntent = intent.cloneFilter();
            abort |= !mService.mController.activityStarting(watchIntent,
                    aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }
    ......
    if (abort) {
        ......// 若是 abort 爲true,直接退出
        return START_ABORTED;
    }
    ......
    // 建立 ActivityRecord 對象
    ActivityRecord r = new ActivityRecord(...);
    if (outActivity != null) {
        outActivity[0] = r;
    }
    ......
    // 當前用戶正在操做的 ActivityStack
    final ActivityStack stack = mSupervisor.mFocusedStack;
    // 針對常常切換進程的狀況,檢查調用者是否有權限進行進程切換
    if (voiceSession == null && (stack.getResumedActivity() == null
            || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
            // 對於不能切換進程的狀況,把 Activity 信息放入 mPendingActivityLaunches 列表中
            mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                    sourceRecord, startFlags, stack, callerApp));
            ActivityOptions.abort(checkedOptions);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }
    if (mService.mDidAppSwitch) {
        mService.mAppSwitchesAllowedTime = 0;
    } else {
        mService.mDidAppSwitch = true;// 打開開關,容許進程間切換
    }
    // 啓動掛起等待的 Activity,其實就是逐個啓動 mPendingActivityLaunches 列表中的 Activity。
    // 最後也是調用了 startActivity
    // 我的理解,大多數狀況下 mPendingActivityLaunches 列表應該是空的吧
    mController.doPendingActivityLaunches(false);
    ......
    // 調用startActivity另外一個重載方法,第一個參數爲 ActivityRecord
    return startActivity(r, ...);
}
private int startActivity(final ActivityRecord r, ...) {
    int result = START_CANCELED;
    ......
    result = startActivityUnchecked(r, ...);
    ......
    return result;
}
複製代碼

這裏其實不用記錄太多細節,重要的是瞭解啓動Activity方法的調用流程,這裏最後調用的是startActivityUnchecked()方法,咱們來繼續看下。

ActivityStarter.startActivityUnchecked()

方法以下:

private int startActivityUnchecked(final ActivityRecord r, ...) {
    // 初始化環境和lunchModeFlags 
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);
    computeLaunchingTaskFlags();
    computeSourceStack();
    mIntent.setFlags(mLaunchFlags);

    // 判斷 Activity 是否須要插入新的 Task,如下狀況 reusedActivity 不爲空
    // 1.設置了FLAG_ACTIVITY_NEW_TASK:
    // 2.啓動模式爲singleTask:
    // 3.啓動模式爲singleInstance
    ActivityRecord reusedActivity = getReusableIntentActivity();
    ......
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.realActivity.equals(mStartActivity.realActivity)
            && top.userId == mStartActivity.userId
            && top.app != null && top.app.thread != null
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
    if (dontStart) { // 不須要啓動的狀況
        // For paranoia, make sure we have correctly resumed the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ......
        deliverNewIntent(top);
        ......
        return START_DELIVERED_TO_TOP;
    }
    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTask() : null;
    // 判斷當前 Activity 是否須要一個新的 Task
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        // This not being started from an existing activity, and not part of a new task...
        // just put it in the top task, though these days this case should never happen.
        setTaskToCurrentTopOrCreateNewTask();
    }
    ......
    // 啓動 Activity
    // startActivityLocked 這裏主要是將 ActivityRecord 對象加入到 Task 的頂部
    // 同時將 Task 添加到 mTaskHistory 的頂部
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    // 利用 WindowManager 使 Activity 可見
    if (mDoResume) {
        final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) {
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            mService.mWindowManager.executeAppTransition(); // 此處應該是執行應用間的切換動畫
        } else {
            .......
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else if (mStartActivity != null) {
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    }
    ......
    return START_SUCCESS;
}
複製代碼

startActivityUnchecked()方法主要是經過Intent的標誌和Activity的屬性來肯定ActivityTask,而後將其調整至棧頂,細節咱們先略過,須要重點關注的方法是mSupervisor.resumeFocusedStackTopActivityLocked()方法的調用。跟蹤調用就會發現,最後執行的是ActivityStack類的resumeTopActivityInnerLocked()方法

ActivityStack.resumeTopActivityInnerLocked()

咱們前面已經知道resumeFocusedStackTopActivityLocked()方法最終會調用ActivityStack類的resumeTopActivityInnerLocked()方法。

resumeTopActivityInnerLocked()方法主要的做用是將位於棧頂的Activity顯示出來,不過在此以前,舊的Activity(變量mResumedActivity引用的就是)還顯示在屏幕上。方法內容以下:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    if (!mService.mBooting && !mService.mBooted) {
        // Not ready yet!
        return false;
    }
    // 從要 mTaskHistory 中查找要啓動的 Activity
    // 這裏這樣作應該是由於前面已經將 Activity 放入堆棧中了
    final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    final boolean hasRunningActivity = next != null;
    ......
    if (!hasRunningActivity) {
        // There are no activities left in the stack, let's look somewhere else.
        return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
    }
    next.delayedResume = false;
    // 若是當前顯示的 Activity 就是要啓動的 Activity,直接返回
    if (mResumedActivity == next && next.isState(RESUMED)
            && mStackSupervisor.allResumedActivitiesComplete()) {
        executeAppTransition(options);
        return false;
    }
    // 若是正在休眠或者關機,直接返回
    if (shouldSleepOrShutDownActivities()
            && mLastPausedActivity == next
            && mStackSupervisor.allPausedActivitiesComplete()) {
        executeAppTransition(options);
        return false;
    }
    // user 狀態檢查
    if (!mService.mUserController.hasStartedUserState(next.userId)) {
        return false;
    }
    // 將要啓動的 Activity 從相關隊列中移除
    mStackSupervisor.mStoppingActivities.remove(next);
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    next.sleeping = false;
    mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
    // 檢查是否有正在 Pause 的 Activity
    if (!mStackSupervisor.allPausedActivitiesComplete()) {
        return false;
    }
    // 設置要啓動的 applicationInfo
    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
    ......
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
    if (mResumedActivity != null) {
        // 暫停當前 Activity
        // startPausingLocked() 中便會觸發 舊Activity 的 onPause() 操做
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    ......
    ActivityStack lastStack = mStackSupervisor.getLastStack();
    if (next.app != null && next.app.thread != null) {
        // 若是 Activity 所在的應用已經存在,只須要把 Activity 顯示出來
        ......
        synchronized(mWindowManager.getWindowManagerLock()) {
            // This activity is now becoming visible.
            if (!next.visible || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
            }
            ......
            try {
                final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
                        next.appToken);
                ......
                // 若是當前 Activity 還有等待返回的結果,添加 ActivityResultItem,
                // 其中會執行 onActivityResult 回調
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                "Delivering results to " + next + ": " + a);
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }
                // 添加 NewIntentItem,其中會執行 onNewIntent
                if (next.newIntents != null) {
                    transaction.addCallback(NewIntentItem.obtain(next.newIntents,
                            false /* andPause */));
                }
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.repProcState,
                                mService.isNextTransitionForward()));
                mService.getLifecycleManager().scheduleTransaction(transaction);
                ......
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                ......
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }
        }
        ......
    } else {
        // Whoops, need to restart this activity!
        ......
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    ......
    return true;
}
複製代碼

resumeTopActivityInnerLocked()代碼比較長做了精簡,核心邏輯以下:

  • 先是經過startPausingLocked()暫停舊的ActivitystartPausingLocked()方法以下:
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately) {
        ......
        mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                        PauseActivityItem.obtain(prev.finishing, userLeaving,
                                prev.configChangeFlags, pauseImmediately));
        ......
    }
    複製代碼
    • 這裏四不四就和前面的ClientTransaction呼應上了,嘿嘿
  • 若是Activity所在的應用已經啓動,對Activity進行顯示處理,建立ResumeActivityItem進行生命週期通知
    • 最終會致使Activity對象的onResume()方法的執行
  • 若是應用尚未啓動,則調用startSpecificActivityLocked()方法繼續處理,方法以下:
    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // 獲取 Activity 對應的進程
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        if (app != null && app.thread != null) {
            try {
                ......
                // 若是應用進程已經存在的狀況,執行 realStartActivityLocked() 
                // andResume = true
                realStartActivityLocked(r, app, andResume, checkConfig);
                // 而後返回
                return;
            } catch (RemoteException e) {
            }
    
        }
        // Activity 對應的進程爲空,經過 AMS 的 startProcessLocked() 建立新的進程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    複製代碼
    • 核心方法是realStartActivityLocked(),就算是從新啓動進程的狀況,最後執行的也是realStartActivityLocked()

ActivityStackSupervisor.realStartActivityLocked()

對於realStartActivityLocked()方法,咱們簡單看下和生命週期相關的內容:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
        ......
        // Create activity launch transaction.
        final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
        // 添加 LaunchActivityItem,這個會觸發 onCreate 方法
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), ...);
        // 設置最終狀態,resume 仍是 pause
        final ActivityLifecycleItem lifecycleItem;
        // 根據前面的調用參數能夠肯定,andResume = true
        if (andResume) {
            // 設置最終狀態爲 ON_RESUME
            lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
        // Schedule transaction.
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        ......
        return true;
    }
複製代碼

方法中添加了LaunchActivityItemResumeActivityItem類的對象,並調用了scheduleTransaction()方法。

LaunchActivityItem屬於比較複雜的調用邏輯

LaunchActivityItem類爲例,咱們來看跟蹤下調用關係:

public class LaunchActivityItem extends ClientTransactionItem {
    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        ......
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        ......
    }
}
複製代碼

調用的是ActivityThreadhandleLaunchActivity()的方法:

public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {
        ......
        final Activity a = performLaunchActivity(r, customIntent);
        ......
        return a;
    }
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
            ......
        } catch (Exception e) {
            ...
        }
        try {
            ......
            if (activity != null) {
                ......
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
            }
            // 將狀態設置爲 ON_CREATE
            r.setState(ON_CREATE);
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            ......
        }
        return activity;
    }
複製代碼

調用的是Instrumentation.callActivityOnCreate()方法,內容以下:

public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
複製代碼

最後經過是調用的Activity.performCreate()方法:

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ......
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ......
    }
複製代碼

到這裏,LaunchActivityItem的邏輯就結束了,也執行完了onCreate()回調,狀態設置爲了ON_CREATE

可是因爲realStartActivityLocked()中設置的最終狀態爲ON_RESUME,當前Activity的狀態不是最終狀態,因此TransactionExecutor還會繼續執行。

相關文章
相關標籤/搜索