Activity啟動流程簡直喪心病狂!

1.前言

小時候聽大人們講四大組件的故事禽额,以為Activity就是手機屏幕上被看到的那東西锯厢。長大以后才發(fā)現(xiàn),原來這個說法只是大人們照顧到孩子的理解能力所編造的謊言脯倒。那么今天实辑,我們就從源碼入手,親眼去看一看Activity是如何啟動的吧藻丢。

2.源碼分析

Activity有2種啟動的方式剪撬,前者是在Launcher界面點擊應(yīng)用的圖標(biāo)、后者是在應(yīng)用中通過Intent進行跳轉(zhuǎn)悠反。我們主要介紹與后者相關(guān)的啟動流程残黑。

2.1 Instrumentation

故事要從Activity的startActivity()開始馍佑,這個方法會在內(nèi)部調(diào)用startActivityForResult(),其中的核心代碼長這樣

Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);

也就是說梨水,Activity是由mInstrumentation來啟動的拭荤。查看Instrumentation類的
execStartActivity()

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

在這里我們見到了老朋友ActivityManagerNative,它是用來與ActivityManagerService進行進程間通信的IBinder對象疫诽。

2.2 ActivityManagerService

回顧一下舅世,在客戶端進程中,我們會調(diào)用ActivityManagerProxy(Proxy)的startActivity()奇徒,經(jīng)過AIDL回調(diào)服務(wù)端進程中ActivityManagerNative(Stub)的onTransact:

 @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        ...
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            ...
         
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
           ...
        }

如上所示雏亚,在服務(wù)端進程,也就是系統(tǒng)進程中摩钙,會真正調(diào)用ActivityManagerService的startActivity()方法罢低。這里多嘴一句,ActivityManagerService在四大組件的創(chuàng)建以及生命周期管理中起了至關(guān)重要的作用胖笛。

startActivity()會轉(zhuǎn)到startActivityAsUser()网持,這個方法會返回mStackSupervisor.startActivityMayWait()方法的結(jié)果。

2.3 ActivityStackSupervisor

現(xiàn)在皮球踢給了ActivityStackSupervisor匀钧。從名字上可以看出翎碑,這是一個Activity棧的管理類谬返,其中有許多不同類型的list用來存放ActivityRecord之斯。
在Android系統(tǒng)中,每個應(yīng)用都有許多自己的棧以及相對應(yīng)的Activity們遣铝,應(yīng)用自己是不會管理這些仔們的生命周期的佑刷,它也管不來。每個應(yīng)用所作的酿炸,就是將Activity的狀態(tài)信息封裝到ActivityRecord并交給系統(tǒng)級的服務(wù)——ActivityStackSupervisor來統(tǒng)一管理瘫絮。因此ActivityStackSupervisor可以很輕松的獲取到各種Activity。


    /** List of processes waiting to find out about the next visible activity. */
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible = new ArrayList<>();

    /** List of processes waiting to find out about the next launched activity. */
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched = new ArrayList<>();

    /** List of activities that are ready to be stopped, but waiting for the next activity to
     * settle down before doing so. */
    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>();
    ...
  

startActivityMayWait()比較長填硕,前面大段代碼都是用來獲取Activity的相關(guān)信息麦萤,比如FLAG、PID扁眯、UID等壮莹,關(guān)鍵代碼1如下:

 ResolveInfo rInfo =
                                AppGlobals.getPackageManager().resolveIntent(
                                        intent, null,
                                        PackageManager.MATCH_DEFAULT_ONLY
                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
                            aInfo = rInfo != null ? rInfo.activityInfo : null;
                            aInfo = mService.getActivityInfoForUser(aInfo, userId);

2.3.1 PackageManagerService

這里負責(zé)去清單文件里查找要啟動的Activity是否存在。我相信大部分同學(xué)都有這樣的經(jīng)歷:直接copy一個Activity到自己的項目中姻檀,運行一跑命满,GG,其報錯信息就是resolveIntent绣版。
AppGlobals.getPackageManager()也是一個AIDL的過程胶台,其返回的IBinder對象是IPackageManager歼疮,按照國際慣例,我們找到其本尊PackageManagerService的resolveIntent()方法:

 @Override
    public ResolveInfo resolveIntent(Intent intent, String resolvedType,
            int flags, int userId) {
        if (!sUserManager.exists(userId)) return null;
        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
        return chooseBestActivity(intent, resolvedType, flags, query, userId);
    }

這里有一個List<ResolveInfo> 用來存符合要求的Activity诈唬,為什么會返回list呢韩脏?因為隱式啟動時,有可能會匹配一個以上的activity铸磅,所以在最后return方法中骤素,chooseBestActivity 就用來根據(jù)不同情況選擇合適的Activity,比如優(yōu)先級不同時自動返回最佳的愚屁、有默認值時直接返回默認的济竹、優(yōu)先級相同時讓用戶選擇等等。

這里還要再介紹一下PackageManagerService霎槐,這是用來管理android中“包”的系統(tǒng)服務(wù)送浊,它會掃描各個APK的AndroidManifest.xml中四大組件的注冊信息并保存在自己那里,證據(jù)就在它自己的構(gòu)造函數(shù)里:

File dataDir = Environment.getDataDirectory();
            mAppDataDir = new File(dataDir, "data");
            mAppInstallDir = new File(dataDir, "app");
            mAppLib32InstallDir = new File(dataDir, "app-lib");
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();
            mUserAppDataDir = new File(dataDir, "user");
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
            ...
            scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

            ...

而這個服務(wù)是在SystemServer中啟動的丘跌,啟動后會調(diào)用其main方法袭景,并把自己交給系統(tǒng)服務(wù)的管理類(大多數(shù)系統(tǒng)服務(wù)都是這樣玩的)

PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        ServiceManager.addService("package", m);

2.3.2 ActivityRecord

接下來回到ActivityStackSupervisor.startActivityMayWait()中,關(guān)鍵代碼2如下:

int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);

這里調(diào)用了startActivityLocked闭树,這個方法主要用來驗證intent耸棒、Class、Permission等报辱,其中有許多if語句對err進行了判斷与殃。

 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

判斷完成之后,如果沒有任何異常碍现,就會創(chuàng)建一個ActivityRecord對象幅疼。從下面的構(gòu)造方法中可以看出,ActivityRecord封裝了與Activity有關(guān)的一系列參數(shù)昼接,比如我是誰爽篷,我從哪里來,我要到哪里去慢睡。

ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);

到此startActivityLocked()就基本完成了歷史使命逐工,在它代碼的最后,新時代的接力棒又交到了startActivityUncheckedLocked()手上

err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

2.4 ActivityStack

新時代一開始漂辐,就結(jié)合Flag與啟動模式開始大清洗泪喊,得出當(dāng)前Activity真正的啟動模式

 final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
        final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
        final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;

        int launchFlags = intent.getFlags();
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                (launchSingleInstance || launchSingleTask)) {
            // We have a conflict between the Intent and the Activity manifest, manifest wins.
            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                    "\"singleInstance\" or \"singleTask\"");
            launchFlags &=
                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        } 

獲得啟動模式后,自然要開始準備與Task有關(guān)的內(nèi)容者吁。比如判斷是否要獨立分配一個棧窘俺,如果需要則創(chuàng)建、如果不需要則再判斷瘤泪,是否要將當(dāng)前Actitivy移動到當(dāng)前Task的最前面灶泵。
這個方法里還有許多許多if判斷語句,可見Activity作為四大組件之首果然名不虛傳,其啟動流程是極其復(fù)雜與嚴謹?shù)摹?/p>

final ActivityStack focusStack = getFocusedStack();
                    ActivityRecord curTop = (focusStack == null)
                            ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
                    boolean movedToFront = false;
                    if (curTop != null && (curTop.task != intentActivity.task ||curTop.task != focusStack.topTask())) {
                         ...
                            movedHome = true;
                         ...
                         }

我們不停的向下滑動鼠標(biāo)膳犹,快速瞻仰一下Google工程師的偉大,慢慢就到了代碼的最底部钠惩。

targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);

文章之前說過,ActivityStackSupervisor是用來管理ActivityStack的愧沟,在前面一萬個判斷中渴频,我們已經(jīng)獲得了當(dāng)前的ActivityStack以及封裝Activity信息的ActivityRecord。所以接下來批钠,就應(yīng)該進入到ActivityStack中去執(zhí)行具體的棧操作忙上。

現(xiàn)在對ActivityStack本身操作。在系統(tǒng)中涮毫,對ActivityStack的管理也是基于棧這種結(jié)構(gòu)的咒吐,暫且稱之為stack棧。既然啟動了新的Activity硅确,那么該Activity所屬的ActivityStack自然也要移動到stack棧的頂端菱农。
下面有兩種情況,一是Activity啟動了新的ActivityStack:

   if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            insertTaskAtTop(rTask, r);
            mWindowManager.moveTaskToTop(taskId);
        }

此時將新的ActivityStack移動到stack棧的最頂端舅巷,同時也要將對應(yīng)的Window置頂媚值。

第二種情況是Activity還在原來的棧中運行嚼松,此時就將Activity移動到ActivityStack的頂端

        if (!newTask) {
         ...
         task.addActivityToTop(r);
         ...
                        
        }

2.5 pause與resume的江湖傳說

在方法最后,代碼又從ActivityStack回到了mStackSupervisor中:

 if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }

resumeTopActivitiesLocked中,首先判斷了當(dāng)前棧是否是Top棧肄扎,如果沒有問題辆雾,就回到ActivityStack中

 if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

resumeTopActivityLocked()又調(diào)用了resumeTopActivityInnerLocked(),這個方法里重點就來了:

 // We need to start pausing the current activity so the top one
        // can be resumed...
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }

看到這句注釋了嗎政鼠,江湖上一直流傳的前一個Activity先pause公般,后一個Activity再resume的說法昧谊,原來是從這里來的遏佣!

2.5.1 onPause的故事

接著深入進去瞧瞧startPausingLocked()到底做了些什么。

 ActivityRecord prev = mResumedActivity;
 ...
 if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        }

首先揽浙,這里有一個叫pre的ActivityRecord状婶,顧名思義,這是當(dāng)前Activity的上一個Activity馅巷。如果pre的應(yīng)用不為空膛虫,則通過prev.app.thread.schedulePauseActivity()來執(zhí)行具體的pause操作。
在這里钓猬,我們必須先來理清楚一個概念稍刀,ActivityStackSupervisor只是用來管理Activity與任務(wù)棧的,它并不具備執(zhí)行具體操作的能力敞曹。
因此在這里是通過IPC告訴要暫停的Activity進入暫停账月。其具體的操作是在ActivityThread中執(zhí)行的:

 public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

這里向Handler H發(fā)送了H.PAUSE_ACTIVITY的Message,H是這樣處理回調(diào)的:

 case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

handlePauseActivity()也是比較關(guān)鍵的方法

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
            ...
            //注釋1
            performPauseActivity(token, finished, r.isPreHoneycomb());
            ...
            //注釋2
            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

先看注釋1處澳迫,這里調(diào)用了performPauseActivity()局齿,performPauseActivity()又調(diào)用了mInstrumentation.callActivityOnPause(r.activity);,這個方法長這樣:

 public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

去Activity里看看performPause():

final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

當(dāng)當(dāng)當(dāng)當(dāng)~繞了這么一大圈以后橄登, onPause()方法終于得到了回調(diào)抓歼!

2.5.2 onPause之后的故事

現(xiàn)在回到handlePauseActivity()來看注釋2讥此,前面的代碼已經(jīng)執(zhí)行了Activity的onPause(),所以現(xiàn)在要做的是將操作回饋給ActivityManagerService谣妻,來看看它的activityPaused()方法

 @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

因為目標(biāo)Activity已經(jīng)暫停了萄喳,所以現(xiàn)在ActivityManagerService需要知道該讓哪一個Activity上位,此時只能去找被暫停的Activity所屬的ActivityStack尋找答案蹋半。
activityPausedLocked()中調(diào)用了completePauseLocked(true)來告訴ActivityStack上一個Activity已經(jīng)pause完成了:

if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            if (!mService.isSleepingOrShuttingDown()) {
                mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
            } else {
                mStackSupervisor.checkReadyForSleepLocked();
                ActivityRecord top = topStack.topRunningActivityLocked(null);
                if (top == null || (prev != null && top != prev)) {
                    // If there are no more activities available to run,
                    // do resume anyway to start something.  Also if the top
                    // activity on the stack is not the just paused activity,
                    // we need to go ahead and resume it to ensure we complete
                    // an in-flight app switch.
                    mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
                }
            }
        }

所以接下來通過mStackSupervisor.getFocusedStack()獲取頂層的ActivityStack他巨,再執(zhí)行mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null)來resume某個Activity。

至于為什么要通過mStackSupervisor來獲取頂層棧而不是直接使用當(dāng)前的ActivityStack减江,那是因為有可能被pause的Activity是當(dāng)前ActivityStack中最后的Activity染突。

現(xiàn)在執(zhí)行mStackSupervisor.resumeTopActivitiesLocked(),該方法調(diào)用了targetStack.resumeTopActivityLocked(target, targetOptions)您市,于是我們再次從ActivityStackSupervisor回到ActivityStack觉痛,并且最終調(diào)用了resumeTopActivityInnerLocked()方法。

等等茵休,這個過程是不是有點熟悉薪棒?往前找找,哦榕莺,原來之前通過startPausingLocked()開始pause一個Activity時也是走的這個流程俐芯,只不過現(xiàn)在改成resume另一個Activity了。

2.5.3 新進程的創(chuàng)建

我們來重新感受一下resumeTopActivityInnerLocked()钉鸯,這里有一個很長if-else語句用來驗證是否該需要啟動的Activity所在進程和app已經(jīng)存在吧史,若存在,直接啟動唠雕,否則準備創(chuàng)建該進程贸营。

 if (next.app != null && next.app.thread != null) {
       ...
 } else {
       ...
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

我們重點關(guān)注創(chuàng)建進程的方法,這個startSpecificActivityLocked()再次進行了一波進程是否存在的判斷岩睁,接著會調(diào)用ActivityManagerService的startProcessLocked()開始進程的創(chuàng)建钞脂。這個創(chuàng)建的過程也是相當(dāng)兇殘的,在這里就先簡潔了當(dāng)?shù)慕榻B一下:

 if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);

Process.start()完成了ActivityThread的創(chuàng)建,之后就會執(zhí)行ActivityThread的main()方法,這一步可謂是知識點豐富凹ù唷!

2.6 ActivityThread

 public static void main(String[] args) {
        ...

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        ...
        Looper.loop();

        ...
    }

大家所熟知的Looper終于在此閃亮登場阎毅,下一篇文章會詳細介紹Looper機制。今天還是先把舞臺交給thread.attach(false)点弯。這個方法感覺熟悉嗎扇调?在之前的window介紹中,我們提到過mWindow是在Activity的attach()方法中初始化的蒲拉,現(xiàn)在就的走進attach好好看一看吧肃拜。

 final IActivityManager mgr = ActivityManagerNative.getDefault();
 try {
                mgr.attachApplication(mAppThread);
            }

mgr是老朋友了痴腌,其本體是IActivityManager雌团,也就是說這里通過AIDL調(diào)用了ActivityManagerService的attachApplication(mAppThread)燃领,而attachApplication(mAppThread)又接著調(diào)用了attachApplicationLocked(thread, callingPid)

 // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

如果此時是正常模式,那就執(zhí)行mStackSupervisor.attachApplicationLocked(app)锦援,堅持住猛蔽,曙光馬上就要來臨了!

 ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                  + hr.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }

還是和之前的流程一樣灵寺,在ActivityStackSupervisor中曼库,先獲取處于棧頂?shù)腁ctivityStack,再通過ActivityStack獲取處于頂層ActivityRecord的略板,最后通過realStartActivityLocked(hr, app, true, true)毁枯,顧名思義,真正的啟動一個Activity叮称。

不過有眼尖的朋友發(fā)現(xiàn)了种玛,這里的if判斷怎么有個條件是hr.app == null呢?要知道瓤檐,雖然之前的代碼中ActivityThread已經(jīng)創(chuàng)建好了赂韵,但此時還沒有與ActivityRecord關(guān)聯(lián)起來,而這正是realStartActivityLocked()要做的挠蛉。

那么Activity要如何真正的啟動呢祭示?
第一步 mWindowManager.setAppVisibility(r.appToken, true);,將該Activity所對應(yīng)的window設(shè)置成可見谴古。
第二步质涛,調(diào)用app.thread.scheduleLaunchActivity(...參數(shù)很長...)方法

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);

scheduleLaunchActivity()中先將參數(shù)封裝成ActivityClientRecord對象,再向Handler H發(fā)送Message掰担。這部分流程和之前說的pause流程相似汇陆,會調(diào)用 handleLaunchActivity(r, null),接著調(diào)用performLaunchActivity(r, customIntent),再通過反射將Activity創(chuàng)建出來恩敌,最后開始Activity生命周期的調(diào)用瞬测。

 Activity activity = null;
        try {
            ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } 

總結(jié)

看到這里,正常人應(yīng)該已經(jīng)暈的不要不要的了纠炮,所以還是需要象征性的總結(jié)一下月趟。

(一)ActivityManagerService(ActivityManagerNative)是核心管理類,負責(zé)組件的管理恢口,在這里主要與ActivityStackSupervisor通信孝宗。
(二)ActivityStackSupervisor管理整個手機任務(wù)棧,即管理著ActivityStack耕肩。
(三)ActivityStack是Activity的棧因妇,即任務(wù)棧问潭,從中可以獲取需要進行操作的ActivityRecord,并且可以對任務(wù)的進程進行操作婚被。
(四)ActivityThread是安卓java應(yīng)用層的入口函數(shù)類狡忙,它會執(zhí)行具體對Activity的操作,并將結(jié)果通知給ActivityManagerService址芯。

完結(jié)撒花~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末灾茁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谷炸,更是在濱河造成了極大的恐慌北专,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旬陡,死亡現(xiàn)場離奇詭異拓颓,居然都是意外死亡,警方通過查閱死者的電腦和手機描孟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門驶睦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人画拾,你說我怎么就攤上這事啥繁。” “怎么了青抛?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵旗闽,是天一觀的道長。 經(jīng)常有香客問我蜜另,道長适室,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任举瑰,我火速辦了婚禮捣辆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘此迅。我一直安慰自己汽畴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布耸序。 她就那樣靜靜地躺著忍些,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坎怪。 梳的紋絲不亂的頭發(fā)上罢坝,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音搅窿,去河邊找鬼嘁酿。 笑死隙券,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闹司。 我是一名探鬼主播娱仔,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼开仰!你這毒婦竟也來了拟枚?” 一聲冷哼從身側(cè)響起薪铜,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤众弓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后隔箍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谓娃,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年蜒滩,在試婚紗的時候發(fā)現(xiàn)自己被綠了滨达。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡俯艰,死狀恐怖捡遍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竹握,我是刑警寧澤画株,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站啦辐,受9級特大地震影響谓传,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芹关,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一续挟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侥衬,春花似錦诗祸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肘习,卻和暖如春际乘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漂佩。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工脖含, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罪塔,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓养葵,卻偏偏與公主長得像征堪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子关拒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容