Android系統源碼分析--Activity啓動過程

關於Activity的源碼分析拖延了過久的時間,因爲最近工做繁忙,加上Activity啓動源碼很是複雜,涉及的內容不少,因此花費了很長是時間纔來寫這篇源碼分析,但願這篇分析能讓咱們很容易的理解Activity的啓動流程,能解決咱們在使用Activity過程當中遇到的問題,這樣就達到了咱們對於源碼分析的目的了。下一篇咱們介紹Activity的finish過程。html

Activity啓動模式簡介:

咱們知道Activity啓動模式有四種,每一種都有不一樣的操做,直接影響咱們App的設計,爲了幫助咱們理解源碼,咱們先分析一下這四種模式。這四種模式包括:standard, singleTop, singleTask 和 singleInstance。java

(下面內容來自:Activity啓動模式圖文詳解:standard, singleTop, singleTask 以及 singleInstanceandroid

  • standard:標準模式,也是默認模式。這種模式是每次你調用startActivity時都會建立一個Activity實例,無論你以前有沒有建立過。git

  • singleTop:從名字能夠分析出是頂部單例,也就是若是你要啓動的Activity在任務棧的頂部,則不會在建立新的Activity實例,而是調用Activity的onNewIntent方法,若是你要啓動的Activity不存在或者存在可是不在任務棧的棧頂,那麼也會建立新的Activity實例而且放置到棧頂位置。所以若是你須要處理Intent中的參數,那麼須要在onCreate方法和onNewIntent方法中都要處理。github

  • singleTask:從名字看是單例模式,這個單例不是棧單例,而是系統單例,也就是若是系統中存在了該Activity,那麼在調用startActivity時並不會從新建立一個Activity,而是將持有這個Activity的任務移動到頂部位置,而且調用onNewIntent方法,同時在這個棧中的該Activity上面的Activity都會被彈出棧而且被銷燬,若是系統中不存在則會建立新的Activity,而且將這個Activity放置到一個新的任務棧中的底部(root)位置。安全

    可是,同一個應用中,咱們正常使用中同一個應用中的Activity啓動卻不是這樣,啓動的具備該屬性的Activity會被放到棧的頂部,而不是放到root(底部)位置,若是須要像上面描述同樣放到root位置,那麼須要在AndroidManifest文件中配置Activity時添加taskAffinity屬性,例如:微信

    <activity android:name=".SingleTaskActivity" android:label="singleTask launchMode" android:launchMode="singleTask" android:taskAffinity="">
    複製代碼

    在不一樣的應用啓動Activity,若是兩個應用啓動具備該屬性的Activity就會建立一個新的任務,而且將該Activity放置到該任務的底部位置。除非用該屬性的Activity所在的應用已經存在了,新建立該屬性Activity後會將其放置到頂部位置。若是在其餘的任務中存在了該屬性的Activity,整個任務都會被移到頂部位置,而且該Activity上面的全部Activity都會被銷燬,用戶須要按back鍵遍歷棧中的Activity才能回到調用者。app

  • singleInstance:單例模式,這個模式和singleTask很類似,不一樣的是:持有這個Activity的任務只有一個Activity,即這個單例自己。若是這個Activity啓動另外一個Activity的時候會自動建立一個任務棧,而且將新啓動的Activity放到該新建立的任務棧中。不過結果很怪異,當具備該模式的Activity啓動另外一個Activity或者另外一個Activity啓動具備該模式的Activity時原本須要建立一個新的任務,可是任務管理中只顯示了一個(最後被移到頂部的那個),致使後臺只顯示一個,咱們不能切換到以前的任務中。若是想切換惟一辦法就是回到Launcher從新點擊應用,可是顯示另個一任務後,第一個任務就會被隱藏了。也就是切換後仍是隻能顯示一個任務。若是想要解決仍然須要設置taskAffinity屬性,例如:ide

    <activity android:name=".SingleTaskActivity" android:label="singleTask launchMode" android:launchMode="singleTask" android:taskAffinity="">
    複製代碼

    這樣就正常了,這種模式不多使用,除非想Launcher這種只有一個Activity,或者100%肯定只有一個Activity。函數

Activity源碼解析

要了解Activity啓動的過程不只要知道代碼流程,也要知道設計流程,咱們先看代碼流程,分析完成後咱們再從新看一下設計流程,來幫助咱們記憶源碼流程。由於篇幅比較長,咱們下面分爲兩個部分分析。

第一部分:

Activity啓動時序圖

Step1.startActivityForResult:

Activity的啓動通常有了兩種方式,一種是須要返回結果的,一種是不須要返回結果的。這裏的函數和咱們上面時序圖中的不同,其實最終調用的方法是這個,另外還有幾個參數不一樣的方法,實際上是同樣的,咱們看最終調用代碼:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            ...
            // Instrumentation是用來監控程序與系統之間的交互操做的,mMainThread的類型爲ActivityThread,
            // 是用來描述應用程序進程的,系統每當啓動一個應用程序進程時,都會在它裏面加載一個ActivityThread
            // 類實體,而且這個類實體會保存在每個在該進程中啓動的Activity組件的父類Activity的成員變量
            // mMainThread中。ActivityThread的成員函數getApplicationThread用來獲取它內部一個類型爲
            // ApplicationThread對象做爲參數傳遞給變量mInstrumentation的成員函數execStartActivity,
            // 以便將它傳遞給AMS,這樣就能夠經過ApplicationThread與Activity交流了。Activity的成員變量
            // mToken的類型爲IBinder,它是Binder代理對象,指向AMS中一個類型爲ActivityRecord對象,用來維護
            // 對應的Activity組件的運行狀態以及信息。此處傳入也是爲了傳遞給AMS,這樣AMS就能夠獲得Activity的
            // 詳細信息了。
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ...
        } else {
            ...
        }
    }
複製代碼

直接啓動時參數requestCode爲-1,這裏執行調用Instrumentation.execStartActivity方法,後面執行ActivityThread.sendActivityResult返回結果,這個方法咱們後面會分析,這裏再也不分析,咱們先看啓動的方法:

Step2.Instrumentation.execStartActivity

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
        ...
            // 獲取AMS的代理對象AMP(ActivityManagerProxy),而後調用起startActivity方法,經過該方法
            // 通知AMS啓動Activity
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            ...
        return null;
    }
複製代碼

這個方法傳入有個參數target,從上面代碼可知傳入的是this,也就是調用啓動Activity方法的Activity,咱們稱之爲調用者或者源Activity。這裏主要是調用startActivity方法,這裏的ActivityManagerNative.getDefault()咱們在前面的文字介紹過是ActivityManagerProxy。

Step3.ActivityManagerProxy.startActivity

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        ...
        // 經過AMP類內部的一個IBinder代理對象想AMS發送一個類型爲START_ACTIVITY_TRANSACTION的進程間通訊請求
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        ...
        return result;
    }
複製代碼

最終調用AMS(ActivityManagerService)的startActivity方法。

Step4.AMS.startActivity

public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
複製代碼

而後調用startActivityAsUser方法。

Step5.AMS.startActivityAsUser

public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        ...
        // mActivityStarter是Activity啓動等操做的管理者
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }
複製代碼

調用ActivityStarter.startActivityMayWait方法。

Step6.ActivityStarter.startActivityMayWait

// 該函數的Wait表示對於outResult的處理上
    final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) {
        ...
        // 是否指定了要啓動Activity相關的組件名,若是指定了組件名則爲顯示啓動,不然爲隱式啓動
        boolean componentSpecified = intent.getComponent() != null;
        ...
        // 收集Intent中的信息
        ...
        synchronized (mService) {
            ...
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask);
            ...
            return res;
        }
    }
複製代碼

這裏主要是收集Intent的內容,進行判斷整理,而後調用startActivityLocked方法。

Step7.startActivityLocked

// Locked 表明非線程安全的,提醒咱們必須保證這些函數是線程安全的,(由於他們涉及不可重入資源的處理)
    final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

        // 獲取調用者進程記錄對象,每個進程都使用一個ProcessRecord對象來描述,而且會保存起來
        ProcessRecord callerApp = null;
        if (caller != null) {
            // mService指向AMS,經過caller來獲取對應的ProcessRecord對象callerApp,參數caller指向
            // 啓動Activity的組件所運行在的應用程序進程的一個ApplicationThread對象,所以ProcessRecord
            // 對象callerApp指向了啓動者所在的應用程序進程(正在啓動的爲被調用者)。
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {// 調用者進程存在
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {// 調用者被系統殺死或者意外退出
                ...
            }
        }
        ...
        ActivityRecord sourceRecord = null;// 調用者Activity封裝
        ActivityRecord resultRecord = null;// 須要接受返回結果的Activity對象封裝
        if (resultTo != null) {// 須要返回結果
            // 查找全部棧中是否存在對應resultTo(調用者)的ActivityRecord
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (sourceRecord != null) {
                // 若是requestCode大於等於0(也就是須要返回結果的啓動Activity),
                // 而且請求者的Activity沒有在等待finish隊列中,說明sourceRecord就是接受結果的Activity
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    // 將啓動者的Activity做爲接受結果的Activity
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags();

        // 直接啓動Activity時requestCode爲-1,所以sourceRecord爲空,resultRecord爲空
        // 這裏對標誌位Intent.FLAG_ACTIVITY_FORWARD_RESULT進行了判斷,咱們先解釋一下這個標誌位:若是A啓動了B
        // 而且須要返回結果,而B須要啓動了C從C返回結果給A,那麼B須要設置Intent.FLAG_ACTIVITY_FORWARD_RESULT標誌
        // 位,而且爲了不衝突B在啓動C時不須要再設置requestCode,而此時sourceRecord是B,resultRecord是A,
        // 就是下面代碼的解釋,設置該標誌後,C調用setResult時結果不會傳遞給B而是傳遞給A。
        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            // Transfer the result target from the source activity to the new
            // one being started, including any failures.
            // 這裏requestCode是B傳過來的,若是設置了上面的標籤,B就不能再設置requestCode,所以,若是
            // requestCode>=0就會產生衝突,所以B不能再設置requestCode
            if (requestCode >= 0) {
                ActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
            // 若是設置了上面的標籤,最終的接受結果的Activity就是B(sourceRecord)中resultTo指向的Activity而不是B
            resultRecord = sourceRecord.resultTo;
            // 若是啓動者resultRecord不在棧中,賦值爲空
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            ...
            requestCode = sourceRecord.requestCode;// 傳遞requestCode
            ...
            if (resultRecord != null) {// 還存在棧中,移除結果
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            ...
        }

        ...
        
        // 不須要返回結果直接啓動Activity時resultRecord爲空
        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

        if (err != START_SUCCESS) {// 失敗
            if (resultRecord != null) {
                // 須要返回結果的啓動Activity,調用Activity.onActivityResult,返回操做取消的結果
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return err;
        }
        ...
        if (abort) {// 若是終止
            if (resultRecord != null) {
                // 等待返回結果的Activity,調用Activity.onActivityResult方法,返回取消操做的結果
                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                        RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return START_SUCCESS;
        }

        // 建立一個ActivityRecord對象r來描述即將被啓動的Activity組件
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
                options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        ...
        // 獲取棧
        final ActivityStack stack = mSupervisor.mFocusedStack;
        // 前面voiceSession傳入爲空,而且沒有可恢復的Activity或者可恢復的Activity不是當前調用者
        if (voiceSession == null && (stack.mResumedActivity == null
                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
            // 前臺棧(stack)尚未resume狀態的Activity時, 則檢查app切換是否容許,不容許切換則要放入等待列表
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                // 不準切換時,獲取啓動新Activity請求的描述,放到等待列表
                PendingActivityLaunch pal = new PendingActivityLaunch(r,
                        sourceRecord, startFlags, stack, callerApp);
                // 添加PendingActivityLaunch
                mPendingActivityLaunches.add(pal);
                ActivityOptions.abort(options);
                return ActivityManager.START_SWITCHES_CANCELED;
            }
        }

        // 容許切換
        if (mService.mDidAppSwitch) {
            mService.mAppSwitchesAllowedTime = 0;// 將切換時間設置爲0
        } else {
            mService.mDidAppSwitch = true;
        }

        // 處理等待啓動的Activity
        doPendingActivityLaunchesLocked(false);

        try {
            ...
            // 啓動目標Activity操做
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
        } finally {
            mService.mWindowManager.continueSurfaceLayout();
        }
        postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
        return err;
    }
複製代碼

上面代碼註釋比較詳細,有一點咱們提一下就是FLAG_ACTIVITY_FORWARD_RESULT標籤,也就是咱們在開發中遇到的一種狀況,ActivityA啓動ActivityB,ActivityB啓動ActivityC,C返回結果讓A接收,咱們平時不知道怎麼處理,經過上面源碼咱們看到能夠設置這個標籤,就能夠完成咱們須要的操做。

上面咱們在啓動失敗的時候回直接返回結果,中斷操做,調用ActivityStack.sendActivityResultLocked方法。

Step8.ActivityStack.sendActivityResultLocked

void sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data) {
        ...
        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
            try {
                ...
                r.app.thread.scheduleSendResult(r.appToken, list);
                return;
            } 
            ...
        }
        ...
    }
複製代碼

這裏會調用ApplicationThreadProxy.scheduleSendResult方法。

Step9.ApplicationThreadProxy.scheduleSendResult

public final void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException {
        ...
        mRemote.transact(SCHEDULE_SEND_RESULT_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
複製代碼

這個咱們以前在上一章分析廣播的時候講過的,最終會調用ActivityThread.scheduleSendResult方法。

Step10.ActivityThread.scheduleSendResult

public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
            ...
            sendMessage(H.SEND_RESULT, res);
        }
複製代碼

這裏經過Handler發送消息到ActivityThread.H.handleMessage中進行處理。而後調用handleSendResult方法

Step12.ActivityThread.handleSendResult

private void handleSendResult(ResultData res) {
        ...
        if (r != null) {
            final boolean resumed = !r.paused;
            ...
            deliverResults(r, res.results);
            if (resumed) {
                r.activity.performResume();
                r.activity.mTemporaryPause = false;
            }
        }
    }
複製代碼

這裏調用deliverResults方法分發結果,分發完成若是須要複用的,則調用複用方法,這個咱們後面會介紹到。

Step13.ActivityThread.deliverResults

private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
        final int N = results.size();
        for (int i = 0; i < N; i++) {
            ...
                r.activity.dispatchActivityResult(ri.mResultWho,
                        ri.mRequestCode, ri.mResultCode, ri.mData);
           ...
        }
    }
複製代碼

這裏調用Activity.dispatchActivityResult方法分發結果。

Step14.Activity.dispatchActivityResult

void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data) {
        ....
            onActivityResult(requestCode, resultCode, data);
        ...
    }
複製代碼

這裏會調用onActivityResult方法,返回結果,其餘的狀況這裏不介紹了,本身分析一下就行了。到此結果返回就完成了,咱們接着分析,再回到Step7,這個方法中有幾個發送返回結果的調用,其實調用都是同樣的,接着咱們分析下面的代碼,調用doPendingActivityLaunchesLocked方法,後面還有startActivityUnchecked方法和postStartActivityUncheckedProcessing方法,其實這兩個方法也是重複調用,也就是doPendingActivityLaunchesLocked裏面也調用了這兩個方法,所以咱們只分析一次就行了。咱們從doPendingActivityLaunchesLocked方法開始分析。

Step16.ActivityStarter.doPendingActivityLaunchesLocked

// 啓動等待列表中的Activity,參數doResume傳遞過來是false
    final void doPendingActivityLaunchesLocked(boolean doResume) {
        while (!mPendingActivityLaunches.isEmpty()) {
            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
            // 若是mPendingActivityLaunches列表中沒有了而且須要複用時設置爲複用,這裏是false
            // (等待列表中最後一個是最後加進來的,因此須要複用時選擇最近的一個進行復用)
            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
            ...
                final int result = startActivityUnchecked(
                        pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
            ...
        }
    }
複製代碼

這裏咱們看到了調用了startActivityUnchecked方法和postStartActivityUncheckedProcessing方法,主要的處理都在startActivityUnchecked方法中,因此下面咱們主要看startActivityUnchecked方法,這個方法調用結束啓動也就結束了。

Step17.ActivityStarter.startActivityUnchecked

/** * 這個方法調用有兩個地方,一個是處理等待的Activity,一個是正常啓動Activity * * @param r 描述須要被啓動的Activity的對象 * @param sourceRecord 調用者的Activity的封裝 * @param voiceSession 等待的爲空,不然不爲空 * @param voiceInteractor 等待的爲空,不然不爲空 * @param startFlags 0 * @param doResume 是否須要複用,等待的不必定須要,直接啓動的須要複用 * @param options 等待的爲空,不然不爲空 * @param inTask 等待的爲空,不然不爲空 * * @return */
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {

        // 設置初始狀態
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);

        computeLaunchingTaskFlags();
        computeSourceStack();
        mIntent.setFlags(mLaunchFlags);
        // 查找有沒有可複用的Activity
        mReusedActivity = getReusableIntentActivity();
        ...
        // 若是有可複用的Activity
        if (mReusedActivity != null) {
            ...
            // mStartActivity是在setInitialState方法中賦值的,指向的是被啓動Activity對象封裝,
            // 若是是第一次啓動那麼它的任務棧就不存在,此時先默認設置成啓動Activity的任務棧。
            if (mStartActivity.task == null) {
                mStartActivity.task = mReusedActivity.task;
            }
            ...
            // 這裏有三個條件,只須要知足一個就執行if語句中的操做
            // 1.須要清理能複用的Activity所在棧中該Activity上面的其餘Activity,
            // 2.該Activity是SingleInstance模式
            // 3.該Activity是SingleTask模式
            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                    || mLaunchSingleInstance || mLaunchSingleTask) {
                // 獲取要啓動Activity
                final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
                        mStartActivity, mLaunchFlags);
                if (top != null) {
                    ...
                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                            mStartActivity.launchedFromPackage);
                }
            }

            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);

            // 將可複用的Activity移到棧頂
            mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);

            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                resumeTargetStackIfNeeded();
                return START_RETURN_INTENT_TO_CALLER;
            }
            setTaskFromIntentActivity(mReusedActivity);

            // 若是不須要添加到任務棧,而且複用TaskRecord爲空,說明沒有啓動一個新的Activity
            // mAddingToTask爲false表示要爲目標Activity組件建立一個專屬任務,事實上函數會檢查這個專屬
            // 任務是否存在,若是已存在,那麼就會將變量mAddingToTask的值設置爲true,
            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything... but it was needed (a.k.a., client don't use that
                // intent!) And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                // 須要啓動的Activity不須要重啓啓動,只須要將其放到棧頂便可
                return START_TASK_TO_FRONT;
            }
        }

        // 找不到對應類(Activity)
        if (mStartActivity.packageName == null) {
            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
                        mStartActivity.requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(mOptions);
            return START_CLASS_NOT_FOUND;
        }

        // If the activity being launched is the same as the one currently at the top, then
        // we need to check if it should only be launched once.
        final ActivityStack topStack = mSupervisor.mFocusedStack;
        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
        ...
        if (dontStart) {// 不啓動
            ...
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            ...
            top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
            ...
            // 須要啓動的Activity在棧頂
            return START_DELIVERED_TO_TOP;
        }

        boolean newTask = false;// 是否會新建立一個任務
        // Activity組件中有一個android:taskAffinity屬性,用來描述它的一個專屬任務,當AMS決定要將目標
        // Activity運行在一個不一樣的任務中時,AMS就會檢查目標Activity組件的專屬任務是否已經存在,若是存
        // 在,那麼AMS就會直接將目標Activity組件添加到它裏面運行,不然,就會先建立這個專屬任務,而後將目
        // 標Activity組件添加到它裏面去運行
        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.task : null;

        // Should this be considered a new task?
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            setTaskFromReuseOrCreateNewTask(taskToAffiliate);
            ...
        } else if (mSourceRecord != null) {
            ...
            final int result = setTaskFromSourceRecord();
            ...
        } else if (mInTask != null) {
            ...
            final int result = setTaskFromInTask();
            ...
        } else {
            ...
            setTaskToCurrentTopOrCreateNewTask();
        }
        ...

        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
        if (mDoResume) {
            if (!mLaunchTaskBehind) {
                // TODO(b/26381750): Remove this code after verification that all the decision
                // points above moved targetStack to the front which will also set the focus
                // activity.
                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
            }
            // 獲取頂部ActivityRecord
            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
            ...
                // 恢復聚焦棧頂Activity
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            ...
        } else {
            // 添加啓動的Activity到最近任務
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
        ...
        return START_SUCCESS;
    }
複製代碼

Activity的啓動最核心的東西就在這個方法中,因此這個方法會很複雜,裏面調用了不少方法,每一個方法分析都會比較複雜,在這個方法最後返回成功,也就是Activity的啓動結束標誌。下面咱們具體分析每一步的具體內容,讓咱們完全瞭解Activity的啓動流程。

Step18.ActivityStarter.setInitialState

private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask, boolean doResume, int startFlags, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
        reset();// 初始化參數
        mStartActivity = r;// 對mStartActivity賦值,也就是被啓動的Activity的對象封裝
        ...
        // 判斷啓動模式,由於默認是standard模式,因此只須要與其餘三個對比就能夠了
        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
        // 經過ActivityOptions.setLaunchTaskBehind方法被激活,而且被啓動完成後就會被清理
        mLaunchTaskBehind = r.mLaunchTaskBehind
                && !mLaunchSingleTask && !mLaunchSingleInstance
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

        sendNewTaskResultRequestIfNeeded();

        ...

        // We'll invoke onUserLeaving before onPause only if the launching
        // activity did not explicitly state that this is an automated launch.
        // 檢查變量mLaunchFlags的Intent.FLAG_ACTIVITY_NO_USER_ACTION位是否爲1,若是等於1,那麼就
        // 表示目標Activity組件不是由用戶手動啓動的,若是目標Activity組件是由用戶手動啓動的,那麼用來
        // 啓動它的源Activity組件就會得到一個用戶離開時間通知,因爲目標Activity組件使用戶在應用程序啓
        // 動器的界面上點擊啓動的,即變量mLaunchFlags的Intent.FLAG_ACTIVITY_NO_USER_ACTION位等於0,
        // 所以,成員變量mUserLeaving的值爲true。
        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0; 
        ...
        if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
            r.mTaskOverlay = true;
            // 查找全部的棧是否存在對應的TaskRecord
            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
            // 若是存在TaskRecord,那麼獲取頂部Activity的ActivityRecord
            final ActivityRecord top = task != null ? task.getTopActivity() : null;
            ...
        }

        // intent的標誌值的位Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP也沒有置位,所以,變量notTop的值爲null。
        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
        ...
    }
複製代碼

這個方法裏面主要是數據初始化,判斷啓動模式,獲取啓動標籤,爲啓動Activity作準備。

Step19.ActivityStarter.adjustLaunchFlagsToDocumentMode

/** * 從前面調用可知,launchFlags是從Intent中獲取的,是目標Activity組件啓動的標誌位,在launchFlags中, * 只有Intent.FLAG_ACTIVITY_NEW_TASK位被標記爲1,其它位都爲0. * * @param r 被啓動Activity對象封裝 * @param launchSingleInstance 是否是SingleInstance模式 * @param launchSingleTask 是否是SingleTask模式 * @param launchFlags 啓動標記 * * @return */
    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance, boolean launchSingleTask, int launchFlags) {
        // 若是launchFlags是FLAG_ACTIVITY_NEW_DOCUMENT模式而且啓動模式是singleInstance或者singleTask
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                (launchSingleInstance || launchSingleTask)) {
            // 若是Intent中的標記爲和manifest中的有衝突,則以manifest中的爲主
            launchFlags &=
                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
        } else {
            ...
        }
        return launchFlags;
    }
複製代碼

這個方法主要是判斷啓動標籤,這裏有個提示,就是若是動態設置的標籤和AndroidManifest裏面配置的衝突,那麼以Manifest文件中爲準。

Step20.ActivityStarter.sendNewTaskResultRequestIfNeeded

private void sendNewTaskResultRequestIfNeeded() {
        // 發送條件:接收結果的Activity存在,而且mLaunchFlags是FLAG_ACTIVITY_NEW_TASK,而且接收結果的任務棧存在
        if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
                && mStartActivity.resultTo.task.stack != null) {
            ...
            mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
            ...
        }
    }
複製代碼

這裏又調用了上面第8步的過程--sendActivityResultLocked方法,這裏就再也不介紹了,沒記住的能夠回去看8-14步就能夠了。

Step21.ActivityStack.sendActivityResultLocked

void sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data) {

        ...
                // 調用onActivityResult
                r.app.thread.scheduleSendResult(r.appToken, list);
        ...
    }
複製代碼

這個過程和上面9-15同樣,因此再也不講解。

Step23.ActivityStackSupervisor.anyTaskForIdLocked

調用下面代碼。

Step24.ActivityStackSupervisor.anyTaskForIdLocked

TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents, int stackId) {
        // 這裏的多個顯示通常是可能存在多窗口模式,每個窗口用ActivityDisplay來表示,它包含了當前窗口存在的所
        // 有棧,這裏遍歷全部顯示任務棧中,查找有沒有對應id的任務。
        int numDisplays = mActivityDisplays.size();
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                ActivityStack stack = stacks.get(stackNdx);
                TaskRecord task = stack.taskForIdLocked(id);
                if (task != null) {
                    return task;
                }
            }
        }
        // 根據任務id查找最近任務列表中是否存在該認爲
        TaskRecord task = mRecentTasks.taskForIdLocked(id);
        ...
        return task;
    }
複製代碼

這個方法主要是根據任務棧id查找全部屏幕顯示的任務列表中是否存在該id對應的任務,若是有直接返回,若是沒有從最近任務中查找,沒有直接返回null,若是有則調用restoreRecentTaskLocked方法存儲該任務。

Step25.ActivityStackSupervisor.restoreRecentTaskLocked

private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
        if (stackId == INVALID_STACK_ID) {// 無效的id,咱們前面傳入的就是這個無效的id
            stackId = task.getLaunchStackId();// 獲取當前任務的id
        } else if (stackId == DOCKED_STACK_ID && !task.canGoInDockedStack()) {
            ...
        } else if (stackId == FREEFORM_WORKSPACE_STACK_ID
                && mService.mUserController.shouldConfirmCredentials(task.userId)) {
            ...
        }
        // 當前任務中的棧管理不爲空,說明已經保存了該任務
        if (task.stack != null) {
            // Task has already been restored once. See if we need to do anything more
            if (task.stack.mStackId == stackId) {// 這裏判斷任務棧是否在對的棧管理中。
                // Nothing else to do since it is already restored in the right stack.
                return true;
            }
            // 若是咱們的任務不在對的棧管理中,咱們須要先移除該任務,而後與正確的棧管理進行關聯。
            task.stack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
        }

        ...
        stack.addTask(task, false, "restoreRecentTask");
        ...
        return true;
    }
複製代碼

Step26.ActivityStack.removeTask

void removeTask(TaskRecord task, String reason, int mode) {
        if (mode == REMOVE_TASK_MODE_DESTROYING) {// 長在被徹底移除棧
            mStackSupervisor.removeLockedTaskLocked(task);// 移除鎖定任務
            ...
        }

        final ActivityRecord r = mResumedActivity;
        if (r != null && r.task == task) {// 存在可複用的Activity,而且是咱們正要啓動的Activity
            mResumedActivity = null;
        }

        final int taskNdx = mTaskHistory.indexOf(task);
        final int topTaskNdx = mTaskHistory.size() - 1;
        if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
            // 獲取要移除任務的下一個任務
            final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
            ...
        }
        mTaskHistory.remove(task);// 從歷史記錄移除
        updateTaskMovement(task, true);

        // 該任務模式爲正在被移除銷燬,而且該任務中沒有已經啓動的Activity
        if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
            ...
            // 這裏判斷是否從最近任務移除該任務
            if (task.autoRemoveFromRecents() || isVoiceSession) {
                ...
            }
        }

        // 該棧管理中的歷史任務爲空,也就是所有被清理了或者沒有啓動任務
        if (mTaskHistory.isEmpty()) {
            ...
        }

        task.stack = null;
    }
複製代碼

從當前棧中移除傳入的任務。

Step27.ActivityStack.addTask

void addTask(final TaskRecord task, final boolean toTop, String reason) {
        final ActivityStack prevStack = preAddTask(task, reason, toTop);
        task.stack = this;
        if (toTop) {
            insertTaskAtTop(task, null);
        } else {// 直接插入到歷史任務的最頂部
            mTaskHistory.add(0, task);
            updateTaskMovement(task, false);
        }
        postAddTask(task, prevStack);
    }
複製代碼

將任務插入到棧中,這裏面有個insertTaskAtTop咱們後面再講。

Step28.ActivityStater.computeLaunchingTaskFlags

這個方法主要是對於mLauncherFlags的處理,這裏就再也不貼代碼。

Step29.ActivityStater.computeSourceStack

private void computeSourceStack() {
        // 當前Activity不存在了
        if (mSourceRecord == null) {
            mSourceStack = null;
            return;
        }
        // 若是當前Activity沒有被finish
        if (!mSourceRecord.finishing) {
            mSourceStack = mSourceRecord.task.stack;
            return;
        }

        ...
        // 若是當前Activity正在被finish,而且啓動模式不是啓動一個新的任務,那麼咱們要添加啓動新任務的標籤。
        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            mNewTaskInfo = mSourceRecord.info;
            mNewTaskIntent = mSourceRecord.task.intent;
        }
        mSourceRecord = null;
        mSourceStack = null;
    }
複製代碼

這裏主要是獲取mSourceStack是否存在。

Step30.ActivityStater.getReusableIntentActivity

/** * 決定新的Activity是否應該被插入到已經存在的任務棧中。若是不插入,返回null, * 不然返回一個帶有新Activity加入的任務棧的ActivityRecord */
    private ActivityRecord getReusableIntentActivity() {
        // 是否放置到已經存在的任務棧中
        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || mLaunchSingleInstance || mLaunchSingleTask;
        ...
        ActivityRecord intentActivity = null;
        if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
            // 根據Id獲取任務
            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
            // 若是任務存在啓動的Activity就是任務中頂部的Activity
            intentActivity = task != null ? task.getTopActivity() : null;
        } else if (putIntoExistingTask) {// 若是須要放到已存在任務中
            if (mLaunchSingleInstance) {// SingleInstance模式下,在歷史記錄中只有一個Activity的實例,而且它一直在它獨有的任務棧中。
                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
            } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {// 是否是分屏模式
                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
                        !mLaunchSingleTask);
            } else {
                intentActivity = mSupervisor.findTaskLocked(mStartActivity);
            }
        }
        return intentActivity;
    }
複製代碼

這裏是獲取一個可複用的Activity,可能存在,也可能爲null。

Step31.ActivityStackSupervisor.anyTaskForIdLocked

這裏方法和上面23同樣,因此不在講解,咱們接着看36步。

Step36.ActivityStackSupervisor.findActivityLocked

// 查找棧中是否存在與被啓動Activity相同的Activity,若是存在取第一個返回,不存在返回空
    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityRecord ar = stacks.get(stackNdx)
                        .findActivityLocked(intent, info, compareIntentFilters);
                if (ar != null) {
                    return ar;
                }
            }
        }
        return null;
    }
複製代碼

根據for循環來查找對應的Activity。

Step37.ActivityStack.findActivityLocked

ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
        ...

        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            ...
        }

        return null;
    }
複製代碼

從棧頂開始,返回第一個與該要啓動的Activity相同的Activity,若是沒有則返回空

Step38.ActivityStackSupervisor.findTaskLocked

ActivityRecord findTaskLocked(ActivityRecord r) {
        ...
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                ...
                // 查找棧中是否存在對應的Activity
                stack.findTaskLocked(r, mTmpFindTaskResult);
                ..
            }
        }
        if (DEBUG_TASKS && mTmpFindTaskResult.r == null) Slog.d(TAG_TASKS, "No task found");
        return mTmpFindTaskResult.r;
    }
複製代碼

這裏考慮到了分屏,查找全部屏幕上是否存在對應的Activity。

Step39.ActivityStack.findTaskLocked

這個方法沒有太複雜的東西,因此再也不貼代碼,主要根據傳入的參數查找存在該Activity的task。

Step40.TaskRecord.performClearTaskForReuseLocked

ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
        ...
        final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
        ...
    }
複製代碼

調用performClearTaskLocked方法:

Step41.TaskRecord.performClearTaskLocked

final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
        int numActivities = mActivities.size();
        for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
            ActivityRecord r = mActivities.get(activityNdx);
            if (r.finishing) {// 若是正在finish過濾掉
                continue;
            }
            // 若是是要找的Activity,則finish掉所在棧中上面的全部Activity
            if (r.realActivity.equals(newR.realActivity)) {// 判斷ComponentName(包名類名)
                // Here it is! Now finish everything in front...
                // 若是包名類名同樣,則說明就是要找的和被啓動Activity同樣的Activity,其實就是要啓動這個Activity
                final ActivityRecord ret = r;

                for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
                    r = mActivities.get(activityNdx);
                    if (r.finishing) {
                        continue;
                    }
                    ...
                    // 開始清理要啓動的Activity上面的Activity
                    if (stack != null && stack.finishActivityLocked(
                            r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
                        --activityNdx;
                        --numActivities;
                    }
                }
                ...
            }
        }

        return null;
    }
複製代碼

這裏主要是要清理可複用Activity棧中該Activity頂部的Activity,清理調用ActivityStack.finishActivityLocked方法進行清理,這個方法咱們在下一章Activity的finish過程再講。

Step43.ActivityRecord.deliverNewIntentLocked

final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
        ...
                // 若是正在啓動的Activity已經存在,不須要建立新的Activity,則會調用Activity中的onNewIntent
                app.thread.scheduleNewIntent(
                        ar, appToken, state == ActivityState.PAUSED /* andPause */);
        ...
    }
複製代碼

清理完成後,該可複用Activity就會到達棧頂,此時要調用onNewIntent方法,調用過程就是上面scheduleNewIntent開始,後面的步驟和上面10-15基本同樣因此再也不詳細講解,其實從廣播到Activity啓動聲明週期或者內部方法的調用都是同樣的過程,你只要熟悉一個方法的過程,全部方法的過程就所有都會了,因此這裏仍是比較容易學習的。

Step52.ActivityStarter.setTargetStackAndMoveToFrontIfNeeded

若是可複用的Activity存在那麼就要設置而且將其移到最前面來,也就是棧頂。

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
        // 將要啓動的Activity所在任務所在的棧做爲目標棧
        mTargetStack = intentActivity.task.stack;

        ...
        // 獲取當前焦點棧
        final ActivityStack focusStack = mSupervisor.getFocusedStack();
        // 獲取焦點棧中最上面正在運行的非延遲Activity
        ActivityRecord curTop = (focusStack == null)
                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);

        // 這裏三個條件:
        // 1.存在上面獲取的Activity,
        // 2.該Activity和要啓動Activity不在同一個任務,或者該Activity不是最頂部的任務(也就是否是第一個任務)
        // 3.須要移動到頂部
        if (curTop != null
                && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
                && !mAvoidMoveToFront) {
            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
            // 源Activity不存在或者源Activity所在棧頂部Activity存在而且頂部Activity和源Activity不在同一個任務中
            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
                    mSourceStack.topActivity().task == mSourceRecord.task)) {
                ...
                // 是否建立新任務而且清理該任務中的其餘Activity
                final boolean willClearTask =
                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
                if (!willClearTask) {// 不清理
                    // 獲取啓動棧
                    final ActivityStack launchStack = getLaunchStack(
                            mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
                    // 若是啓動棧不存在,或者啓動棧不是目標棧
                    if (launchStack == null || launchStack == mTargetStack) {
                        // We only want to move to the front, if we aren't going to launch on a
                        // different stack. If we launch on a different stack, we will put the
                        // task on top there.
                        // 把目標棧移動到前臺
                        mTargetStack.moveTaskToFrontLocked(
                                intentActivity.task, mNoAnimation, mOptions,
                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                        mMovedToFront = true;// 標記
                    } else if (launchStack.mStackId == DOCKED_STACK_ID
                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
                        // 若是是分屏模式,被啓動的Activity會顯示到啓動它的Activity所在屏幕上
                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                            mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
                                    launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
                                    ANIMATE);
                        } else {// 不是分屏模式
                            mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
                                    mOptions, mStartActivity.appTimeTracker,
                                    "bringToFrontInsteadOfAdjacentLaunch");
                        }
                ...
            }
        }
        ...
        return intentActivity;
    }
複製代碼

這裏相對操做複雜,就是若是知足上面三個條件,就要將目標任務移動到前臺來,這裏調用了兩個方法:mTargetStack.moveTaskToFrontLocked和mSupervisor.moveTaskToStackLocked。咱們先看第一個:

Step53.ActivityStack.moveTaskToFrontLocked

final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, String reason) {
        ...
        insertTaskAtTop(tr, null);

        ...
            addRecentActivityLocked(top);
        ...

        // Set focus to the top running activity of this stack.
        ActivityRecord r = topRunningActivityLocked();
        mService.setFocusedActivityLocked(r, reason);

        ...

        mStackSupervisor.resumeFocusedStackTopActivityLocked();
        ...
    }
複製代碼

這裏有幾個操做:將任務插入到頂部,將最頂部的Activity描述對象放到最近任務的列表中,獲取頂部運行的Activity並將其設置爲聚焦Activity,咱們一個一個分析。

Step54.ActivityStack.insertTaskAtTop

// 插入任務到頂部
    private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) {
        boolean isLastTaskOverHome = false;
        // If the moving task is over home stack, transfer(轉移) its return type to next task
        if (task.isOverHomeStack()) {// 當前任務不是普通應用任務
            // 獲取相同用戶下當前任務的下一個任務
            final TaskRecord nextTask = getNextTask(task);
            if (nextTask != null) {// 存在下一個任務,
                // 則將下一個任務返回任務的類型設置爲插入任務的類型
                nextTask.setTaskToReturnTo(task.getTaskToReturnTo());
            } else {// 若是不存在,那麼當前任務就是最後一個了
                isLastTaskOverHome = true;
            }
        }

        // If this is being moved to the top by another activity or being launched from the home
        // activity, set mTaskToReturnTo accordingly(相應的).
        if (isOnHomeDisplay()) {// 默認顯示屏
            // 獲取上一個有焦點的棧管理
            ActivityStack lastStack = mStackSupervisor.getLastStack();
            final boolean fromHome = lastStack.isHomeStack();
            if (!isHomeStack() && (fromHome || topTask() != task)) {
                // If it's a last task over home - we default to keep its return to type not to
                // make underlying task focused when this one will be finished.
                int returnToType = isLastTaskOverHome
                        ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
                if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
                    returnToType = lastStack.topTask() == null
                            ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
                }
                task.setTaskToReturnTo(returnToType);
            }
        } else {
            task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
        }

        // 從歷史任務中移除該任務
        mTaskHistory.remove(task);
        // Now put task at top.插入任務到頂部
        int taskNdx = mTaskHistory.size();
        // 判斷是否顯示
        final boolean notShownWhenLocked =
                (newActivity != null && (newActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0)
                        || (newActivity == null && task.topRunningActivityLocked() == null);
        // 若是插入任務不是當前用戶的任務,而且也不進行顯示
        if (!mStackSupervisor.isCurrentProfileLocked(task.userId) && notShownWhenLocked) {
            // Put non-current user tasks below current user tasks.
            // 這裏說明插入的任務不是當前用戶的任務,那麼從頂部向下查找,一直找到第一不是當前用戶的任務的位置,
            while (--taskNdx >= 0) {
                final TaskRecord tmpTask = mTaskHistory.get(taskNdx);
                if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
                        || tmpTask.topRunningActivityLocked() == null) {
                    break;
                }
            }
            // 若是插入的任務不是當前用戶的,那麼就將該非當前用戶任務插入到當前用戶的任務下面而且在不是當前用戶
            // 的任務上面,也就是若是插入任務不是當前用戶的那麼就要將該任務插入到當前用戶任務和非當前用戶任務中間
            ++taskNdx;
        }
        // 插入任務
        mTaskHistory.add(taskNdx, task);
        updateTaskMovement(task, true);
    }
複製代碼

這裏面主要是要考慮插入的任務是否是當前用戶的任務,若是不是要依次查找非當前用戶任務位置,而後將其放置到非當前用戶任務的頂部位置。55步是將其添加到最近任務記錄中。56步是獲取頂部運行的Activity的描述對象。

Step57.ActivityManagerService.setFocusedActivityLocked

boolean setFocusedActivityLocked(ActivityRecord r, String reason) {
        ...
        // 將要啓動的Activity移動到前臺
        if (mStackSupervisor.moveActivityStackToFront(r, reason + " setFocusedActivity")) {
            mWindowManager.setFocusedApp(r.appToken, true);
        }
        ...
        return true;
    }
複製代碼

這裏主要是經過調用ActivityStackSupervisor.moveActivityStackToFront方法移動焦點到新的Activity。

Step58.ActivityStackSupervisor.moveActivityStackToFront

// 將要啓動的Activity移動到前臺
    boolean moveActivityStackToFront(ActivityRecord r, String reason) {
        ...
        // 將任務移動到前臺
        task.stack.moveToFront(reason, task);
        return true;
    }
複製代碼

Step59.ActivityStack.moveToFront

void moveToFront(String reason, TaskRecord task) {
        ...
            mStackSupervisor.setFocusStackUnchecked(reason, this);
        ...
            insertTaskAtTop(task, null);
        ...
    }
複製代碼

將任務移動到頂部,方法講過了看上面的代碼分析。

Step60.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }
複製代碼

Step61.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {// 若是目標棧存在而且處於聚焦狀態,直接啓動
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        // 若是目標棧不存在或者沒有在聚焦狀態,則從聚焦棧中取出棧頂的Activity
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }
複製代碼

Step62.ActivityStack.resumeTopActivityUncheckedLocked

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        ...
            result = resumeTopActivityInnerLocked(prev, options);
        ...
    }
複製代碼

最終調用resumeTopActivityInnerLocked方法來進行處理,這個比較複雜,咱們放到第二部分分析。咱們回到前面接着分析。

Step63.ActivityStackSupervisor.moveTaskToStackLocked

boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus, String reason, boolean animate) {
        return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate,
                false /* deferResume */);
    }
複製代碼

Step64.ActivityStackSupervisor.moveTaskToStackLocked

boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus, String reason, boolean animate, boolean deferResume) {
        // 根據id獲取Task描述對象TaskRecord
        final TaskRecord task = anyTaskForIdLocked(taskId);
        ...
            resumeFocusedStackTopActivityLocked();
        ...
    }
複製代碼

第一個方法咱們前面已經分析過了,這裏再也不提,第二個方法咱們上面Step60已經分析過了。

Step65.ActivityStarter.resumeTargetStackIfNeeded

// 恢復目標棧
    private void resumeTargetStackIfNeeded() {
        ...
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
        ...
    }
複製代碼

這裏就是上面64中的方法也就是60步。

Step66.ActivityStarter.setTaskFromIntentActivity

這個方法主要是目標ActivityRecord對象中獲取task。代碼很少,能夠本身看看。

Step68.ActivityStarter.setTaskFromReuseOrCreateNewTask

private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
                mOptions);

        if (mReuseTask == null) {// 沒有可用任務
            // 建立新的任務並插入棧中
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
            mStartActivity.setTask(task, taskToAffiliate);
            ...
        } else {
            mStartActivity.setTask(mReuseTask, taskToAffiliate);
        }
    }
複製代碼

若是沒有可複用的任務就須要建立新的任務,而且添加,若是有就直接添加。

Step71.ActivityStack.startActivityLocked

// 啓動Activity(Locked表示線程安全的)
    final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            // task中的上一個activity已被移除,或者AMS重用該task,則將該task移到頂部
            insertTaskAtTop(rTask, r);
            mWindowManager.moveTaskToTop(taskId);
        }
        
        // 將目標Activity放到棧頂
        task.addActivityToTop(r);
        task.setFrontOfTask();

        ...
    }
複製代碼

這裏就是將Activity放到棧頂,而後顯示。

Step72.ActivityStack.addRecentActivityLocked

這個方法在55步分析過再也不分析。

這裏是第一部分的,所以啓動過程很複雜因此時序圖不少,只能分兩部分來說,不少的代碼沒有分析,須要的能夠去忘得coding拉取代碼來看,裏面有註釋。

第二部分:

Activity啓動時序圖

這一部分是上面過程的中間一段過程,因爲東西比較多,時序圖無法畫了,因此提取出來單獨分析,主要是ActivityStack.resumeTopActivityInnerLocked方法。

Step1.ActivityStack.resumeTopActivityInnerLocked

/** * 1.當找不到須要resume的Activity,則直接回到桌面; * 2.不然,當mResumedActivity不爲空,則執行startPausingLocked()暫停該activity; * 3.而後再進入startSpecificActivityLocked環節。 * * @param prev 源Activity對象 * @param options * * @return */
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...

        // Find the first activity that is not finishing.
        // 前面咱們把要啓動的Activity放置在當前Activity組件堆棧的頂端,而且它是正在等待啓動的,即它不是
        // 處於結束狀態的,所以next就指向了咱們將要啓動的Activity組件
        final ActivityRecord next = topRunningActivityLocked();

        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        // 將mUserLeaving放置在userLeaving中,而且重置mUserLeaving爲false,所以就能夠經過userLeaving
        // 判斷是否須要向源Activity組件發送一個用戶離開的時間通知了
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        final TaskRecord prevTask = prev != null ? prev.task : null;
        if (next == null) {// 若是要啓動的Activity爲空,由於咱們有要啓動的Activity,所以不走這裏
            ...
            if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
                // Try to move focus to the next visible stack with a running activity if this
                // stack is not covering the entire screen.
                return mStackSupervisor.resumeFocusedStackTopActivityLocked(
                        mStackSupervisor.getFocusedStack(), prev, null);
            }
        ...
        
        // 暫停其餘Activity
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
        // 咱們從一個Activity啓動另外一個Activity的時候,源Activity不是空,mResumedActivity指向源Activity,
        // 所以mResumedActivity不爲空
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            // 檢測是否正在終止一個Activity組件,若是是,那麼要等到它停止完成以後再啓動Activity組件next
            pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
        }
        ...

        // If the most recent activity was noHistory but was only stopped rather
        // than stopped+finished because the device went to sleep, we need to make
        // sure to finish it as we're making a new activity topmost.
        if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
                !mLastNoHistoryActivity.finishing) {
            ...
            requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                    null, "resume-no-history", false);
            ...
        }

        ...
                        // 調用onActivityResult函數
                        next.app.thread.scheduleSendResult(next.appToken, a);
                    ...
                    next.app.thread.scheduleNewIntent(
                            next.newIntents, next.appToken, false /* andPause */);
                ...
                // 觸發onResume()
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

                ...
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                ...
                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                        "resume-exception", true);
            ...
            // 目標Activity沒有啓動會調用startSpecificActivityLocked來啓動Activity
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
        ...
        return true;
    }
複製代碼

這個函數代碼量很大,我只留下了核心的一些來分析,其餘的能夠對照源碼進行分析。

Step2.ActivityStack.adjustFocusToNextFocusableStackLocked

private boolean adjustFocusToNextFocusableStackLocked(int taskToReturnTo, String reason) {
        final ActivityStack stack = getNextFocusableStackLocked();// 獲取下一個有焦點的棧
        final String myReason = reason + " adjustFocusToNextFocusableStack";
        if (stack == null) {// 沒有能獲取焦點的棧了
            return false;
        }

        // 獲取有焦點的頂部運行的Activity對象
        final ActivityRecord top = stack.topRunningActivityLocked();

        // 若是頂部stack是Launcher或者最近任務所在的stack,而且存在該Activity,而且該Activity沒有顯示
        if (stack.isHomeStack() && (top == null || !top.visible)) {
            // 那麼要顯示Launcher或者最近任務
            return mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, reason);
        }
        return mService.setFocusedActivityLocked(top, myReason);
    }
複製代碼

這裏是獲取下一個可以獲取焦點的棧,好比最近任務或者Launcher,若是獲取不到返回false,若是存在,那麼獲取該棧的頂部Activity,若是是HomeStack也就是Launcher棧或者最近任務棧,而且頂部Activity沒有顯示或者不存在則顯示Launcher或者最近任務界面。不然設置到AMS中做爲焦點Activity,這個函數咱們講過了。

步驟3裏的函數咱們也分析過了,這裏也再也不分析,咱們開始分析第四步。

Step4.ActivityStackSupervisor.pauseBackStacks

boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
        boolean someActivityPaused = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                ...
                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                            dontWait);
                ...
            }
        }
        return someActivityPaused;
    }
複製代碼

經過for循環暫停全部後臺棧中的Activity

Step5.ActivityStack.startPausingLocked

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean dontWait) {
        if (mPausingActivity != null) {
            ...
                completePauseLocked(false, resuming);
        ...
    }
複製代碼

若是須要暫停的Activity不爲空,那麼要完成暫停操做。

Step6.ActivityStack.completePauseLocked

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        ActivityRecord prev = mPausingActivity;

        // 在前面咱們將mPausingActivity指向了與源Activity組件對應的ActivityRecord對象,此處爲true
        if (prev != null) {
            // 表示源Activity狀態已是Paused狀態了
            prev.state = ActivityState.PAUSED;
            if (prev.finishing) {// 若是是正在結束
                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
            } else if (prev.app != null) {// 進程還存在
                ...
                if (prev.deferRelaunchUntilPaused) {
                    // Complete the deferred relaunch that was waiting for pause to complete.
                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
                    relaunchActivityLocked(prev, prev.configChangeFlags, false,
                            prev.preserveWindowOnDeferredRelaunch);
                } 
                ...
            } 

            ...
        }
        ...
    }
複製代碼

finish的過程咱們下一章再分析,咱們下面分析一個核心的函數relaunchActivityLocked,因爲下面會涉及Activity的啓動,所以咱們經過這個函數直接來分析。

Step7.ActivityStack.relaunchActivityLocked

private void relaunchActivityLocked( ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
        ...
            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
                    !andResume, new Configuration(mService.mConfiguration),
                    new Configuration(r.task.mOverrideConfig), preserveWindow);
        ...
    }
複製代碼

看到什麼代碼應該很熟悉了,調用ApplicationThreadProxy.scheduleRelaunchActivity方法而後經過Binder調用ApplicationThread.scheduleRelaunchActivity函數。我這裏的圖就省略了中間的過程。可是要知道這個過程。

Step8.ApplicationThread.scheduleRelaunchActivity

public final void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config, Configuration overrideConfig, boolean preserveWindow) {
            requestRelaunchActivity(token, pendingResults, pendingNewIntents,
                    configChanges, notResumed, config, overrideConfig, true, preserveWindow);
        }
複製代碼

Step9.ActivityThread.requestRelaunchActivity

public final void requestRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config, Configuration overrideConfig, boolean fromServer, boolean preserveWindow) {
        ...
                sendMessage(H.RELAUNCH_ACTIVITY, target);
            ...
    }
複製代碼

這個過程應該很熟悉了,因此這裏再也不多解釋。後面就直接分析過程了。這裏回到ActivityThread.H的handleMessage方法中,而後調用ActivityThread.handleRelaunchActivity方法。

Step10.ActivityThread.handleRelaunchActivity

private void handleRelaunchActivity(ActivityClientRecord tmp) {
        ...
        // Need to ensure state is saved.
        if (!r.paused) {
            performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
        }
        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
            callCallActivityOnSaveInstanceState(r);
        }

        handleDestroyActivity(r.token, false, configChanges, true);

        ...

        handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");

        ...
    }
複製代碼

這裏performPauseActivity會根據12-17步一直執行到Activity.onPause方法。 callCallActivityOnSaveInstanceState方法會執行18-21步驟最終執行Activity.onSaveInstanceState方法。 handleDestroyActivity方法會執行到Activity.onDestroy方法。 這些過程都很簡單跟着代碼走一下就都知道了,過程基本相同。

Step23.ActivityThread.handleLaunchActivity

// 啓動Activity
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ...

        // Make sure we are running with the most recent config.
        // 最終回調目標Activity的onConfigurationChanged()
        handleConfigurationChanged(null, null);

       ...

        // 首先調用performLaunchActivity方法將目標Activity組件啓動起來,最終調用目標Activity的onCreate方法
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            ...
            // 最終回調目標Activity的onStart,onResume.
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
                ...
                performPauseActivityIfNeeded(r, reason);

                ...
        } else {
            ...
        }
    }
複製代碼

上面代碼中handleConfigurationChanged方法最終會調用Activity.onConfigurationChanged方法。handleResumeActivity方法最終會調用Activity.onResume方法。最主要仍是看performLaunchActivity方法。

Step28.ActivityThread.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...

        Activity activity = null;
        try {
            // 將目標Activity的類文件加載到內存中,並建立一個實例。因爲全部Activity組件都是從Activity類
            // 繼承下來的,所以,咱們就能夠將前面建立的Activity組件保存在Activity對象activity中
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        ...

        try {
            // 建立Application對象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

             if (activity != null) {
                ...
                // 使用ContextImpl對象appContext和ActivityClientRecord對象r來初始化Activity對象activity
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);

                ...
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                // 調用成員變量mInstrumentation的callActivityOnCreate方法將Activity對象activity啓動起來,
                // 會調用Activity的onCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                ...
            }
        ...

        return activity;
    }
複製代碼

這個啓動過程: 經過29步加載Activity, 而後經過31步建立Application, 在35步調用Application的onCreate方法, 37步調用Activity的attach方法, 38步設置主題, 39步調用Activity的onCreate方法, 42步調用Activity的onStart方法, 45步調用Activity的onRestoreInstanceState方法, 而後回到ActivityThread.handleLaunchActivity方法執行handleResumeActivity方法,也就是48步之後; 在調用onResume函數以前可能會先調用onNewIntent方法和onActivityResult方法,這樣一來onResume函數以前的一個流程基本就出來了,因爲代碼比較簡單,這裏再也不貼代碼,本身跟着這個流程本身看看就知道了。

再看65步到67步,這個是從外面調用onActivityResult、onNewIntent和onResume方法的和第一部分的8-15步同樣,能夠參考前面的就行了。

最後68-70步其實仍是會執行到handleLaunchActivity方法上來,因此這裏就再也不分析。

從整篇文章看,Activity的啓動流程是很是複雜,能夠說在四大組件中是最複雜的,可是裏面不少過程是相同的,好比生命週期的每一個方法的調用過程基本是同樣的,所以看書谷歌工程師設計的巧妙,這樣也有助於咱們對於源碼的學習,減小了咱們對於源碼的分析過程,博客寫了不少,可是對於整個過程來講仍是不少地方沒有分析,想了解完整的過程的能夠下載個人代碼,裏面有很全面的註釋,而後本身對着上面的時序圖來進行分析,過幾遍也就熟悉了,我寫這片博客也用了很長的時間,主要是中間老是有事,寫寫停停,時序圖更改了好幾回。中間也有一些問題,不過跟着源碼走仍是都能找到的。

代碼地址:

直接拉取導入開發工具(Intellij idea或者Android studio)

Android_Framework_Source

Android開發羣:192508518

微信公衆帳號:Code-MX

注:本文原創,轉載請註明出處,多謝。

相關文章
相關標籤/搜索