Activity的啟動(dòng)過程分析

緣起

我們在平時(shí)開發(fā)中都知道通過這樣的代碼就可以啟動(dòng)一個(gè)act,如下Context.startActivity(intent),但是你偶爾有沒有想過它內(nèi)部是如何實(shí)現(xiàn)的,或者說系統(tǒng)究竟干了哪些事情,怎么這個(gè)act就顯示在用戶面前呢?作為一個(gè)資深工程師我覺得你起碼應(yīng)該想過這個(gè)問題,下面我們一起來梳理下整個(gè)流程,以下分析基于6.0源碼。

在開始之前我還想啰嗦幾句,其實(shí)啟動(dòng)一個(gè)act的過程,是一個(gè)標(biāo)準(zhǔn)的Android IPC過程,也就是通過Binder機(jī)制實(shí)現(xiàn)的跨進(jìn)程通信,先預(yù)告下,后面慢慢細(xì)說。

過程分析

  1. 一般我們都是通過調(diào)用Activity.startActivity(intent)來啟動(dòng)一個(gè)act的,緊接著它會(huì)調(diào)用其內(nèi)部的startActivityForResult(intent, -1, null )方法,注意這里的requestCode==-1,因?yàn)槲覀儾恍枰祷豶esult;
  2. 接下來調(diào)用到了Instrumentation.execStartActivity()方法,它最終調(diào)用了如下代碼:
    execStartActivity()方法
  3. 上面的ActivityManagerNative.getDefault().startActivity實(shí)際通過Binder機(jī)制調(diào)到了
    另一個(gè)進(jìn)程中的AMS.startActivity方法,代碼如下:
    server/am/ActivityManagerService.java

    接下來在AMS這邊的調(diào)用流程這里簡要羅列下,具體實(shí)現(xiàn)細(xì)節(jié)可以參考源碼,流程如下:
ActivityStackSupervisor.startActivityMayWait -->    
ActivityStackSupervisor.startActivityLocked -->
ActivityStackSupervisor.startActivityUncheckedLocked -->
ActivityStack.resumeTopActivitiesLocked -->
ActivityStack.resumeTopActivityInnerLocked -->
ActivityStackSupervisor.startSpecificActivityLocked -->
ActivityStackSupervisor.realStartActivityLocked

最終在ActivityStackSupervisor.realStartActivityLocked里有這樣的代碼:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

這段代碼很關(guān)鍵,這里app.thread的類型為android.app.IApplicationThread,其源碼大概是這個(gè)樣子:

IApplicationThread.java

  1. IApplicationThread的真正實(shí)現(xiàn)者就是客戶端進(jìn)程中ActivityThread的內(nèi)部類ApplicationThread,我們?nèi)タ囱燮鋵?shí)現(xiàn):


    ApplicationThread實(shí)現(xiàn)

    繞了一個(gè)大圈子,activity的啟動(dòng)流程終于又回到客戶端進(jìn)程了,我們看下ApplicationThread.scheduleLaunchActivity的實(shí)現(xiàn):

        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

可以看到代碼主要是用傳進(jìn)來的參數(shù)構(gòu)造了一個(gè)ActivityClientRecord實(shí)例,然后發(fā)送了一個(gè)LAUNCH_ACTIVITY的msg;

  1. 對此消息的處理實(shí)質(zhì)是調(diào)用了ActivityThread.handleLaunchActivity方法,代碼如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out
                // paused, because it needs to be visible but isn't in the
                // foreground.  We accomplish this by going through the
                // normal startup (because activities expect to go through
                // onResume() the first time they run, before their window
                // is displayed), and then pausing it.  However, in this case
                // we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just
                // retain the current state it has.
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    // We need to keep around the original state, in case
                    // we need to be created again.  But we only do this
                    // for pre-Honeycomb apps, which always save their state
                    // when pausing, so we can not have them save their state
                    // when restarting from a paused state.  For HC and later,
                    // we want to (and can) let the state be saved as the normal
                    // part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
    }

通過其源碼我們發(fā)現(xiàn),它又將重任交給了performLaunchActivity方法,這個(gè)方法主要做了以下幾件事情:
1. 從ActivityClientRecord中獲取待啟動(dòng)act的組件信息;
2. 通過Instrumentation.newActivity方法使用ClassLoader創(chuàng)建act對象;
3. 通過LoadedApk.makeApplication方法創(chuàng)建Application對象,注意如果已經(jīng)有Application對象的話是不會(huì)再次創(chuàng)建的;
4. 創(chuàng)建ComtextImpl對象,并調(diào)用Activity.attach方法完成一些重要數(shù)據(jù)的初始化操作;
5. 最終調(diào)用Activity.onCreate()方法;

至此,act的整個(gè)啟動(dòng)流程就走完了。

總結(jié)

平時(shí)對于我們開發(fā)人員來說,可能還是最后這塊客戶端部分的代碼比較
有用,非常有助于我們的理解,特別是對performLaunchActivity的源碼,有空的話還需要細(xì)細(xì)品味啊。

注:關(guān)于這里第5步更詳細(xì)的文章見這里ActivityThread.handleLaunchActivity方法分析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容