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

通常我們?cè)贏ctivity中啟動(dòng)一個(gè)另一個(gè)Activity钦铁,就是調(diào)用Activity的startActivity方法圣勒,這個(gè)最終會(huì)調(diào)用到Activity的startActivityForResult方法。那你有沒(méi)有想過(guò)Activity的啟動(dòng)到底經(jīng)歷了哪些過(guò)程紊遵,我們今天就來(lái)分析一下蝠检。

在具體分析之前,要先說(shuō)明一下肝箱,Activity的啟動(dòng)流程在細(xì)節(jié)挺繁瑣的,比如啟動(dòng)另一個(gè)App的Activity或者啟動(dòng)不同的launchMode的Activity稀蟋,在細(xì)節(jié)上都會(huì)有不同煌张。我們這次的源碼分析著重分析一下流程,為了簡(jiǎn)單起見(jiàn)退客,就以分析一個(gè)Activity啟動(dòng)app內(nèi)部另一個(gè)standard模式的Activity為主骏融。

Activity啟動(dòng)另一個(gè)Activity之前,當(dāng)前的Activity先要執(zhí)行onPause萌狂,被啟動(dòng)的Activity才會(huì)執(zhí)行到onResume方法档玻。這中間實(shí)際上是會(huì)執(zhí)行4次IPC過(guò)程的:

  • 當(dāng)前Activity發(fā)起啟動(dòng)另一個(gè)Activity的請(qǐng)求——>ActivityManagerService
  • ActivityManagerService——> 通知App暫停當(dāng)前Activity
  • 當(dāng)前App告知已經(jīng)暫停了當(dāng)前的Activity——> ActivityManagerService
  • ActivityManagerService ——> 通知App啟動(dòng)新的Activity

注:本次源碼分析采用Android7.0,不同版本的源碼在細(xì)節(jié)上會(huì)有不同茫藏,比如窃肠,在Android8.0上ActivityManagerService就改成了以AIDL的方式來(lái)寫,請(qǐng)不要太糾結(jié)API的不同刷允。

注:本文Activity啟動(dòng)過(guò)程源碼分析過(guò)程比較長(zhǎng)冤留,代碼較繁瑣,請(qǐng)做好心理準(zhǔn)備树灶。

Activity啟動(dòng)涉及到的類

首先要簡(jiǎn)單介紹一下Activity啟動(dòng)過(guò)程涉及到的類纤怒,以便于更好的理解這個(gè)啟動(dòng)過(guò)程。

  • ActivityThread:App啟動(dòng)的入口
  • ApplicationThread:ActivityThread的內(nèi)部類天通,繼承Binder泊窘,可以進(jìn)程跨進(jìn)程通信。
  • ApplicationThreadProxy:ApplicationThread的一個(gè)本地代理像寒,其它的client端通過(guò)這個(gè)對(duì)象調(diào)用server端ApplicationThread中方法烘豹。
  • Instrumentation:負(fù)責(zé)發(fā)起Activity的啟動(dòng)、并具體負(fù)責(zé)Activity的創(chuàng)建以及Activity生命周期的回調(diào)诺祸。一個(gè)應(yīng)用進(jìn)程只會(huì)有一個(gè)Instrumentation對(duì)象携悯,App內(nèi)的所有Activity都持有該對(duì)象的引用。
  • ActivityManagerService:簡(jiǎn)稱AMS筷笨,是service端對(duì)象憔鬼,負(fù)責(zé)管理系統(tǒng)中所有的Activity
  • ActivityManagerProxy:是ActivityManagerService的本地代理
  • ActivityStack:Activity在AMS的棧管理,用來(lái)記錄已經(jīng)啟動(dòng)的Activity的先后關(guān)系胃夏,狀態(tài)信息等轴或。通過(guò)ActivityStack決定是否需要啟動(dòng)新的進(jìn)程。
  • ActivityRecord:ActivityStack的管理對(duì)象仰禀,每個(gè)Activity在AMS對(duì)應(yīng)一個(gè)ActivityRecord照雁,來(lái)記錄Activity的狀態(tài)以及其他的管理信息。其實(shí)就是服務(wù)器端的Activity對(duì)象的映像答恶。
  • TaskRecord:AMS抽象出來(lái)的一個(gè)“任務(wù)”的概念饺蚊,是記錄ActivityRecord的棧萍诱,一個(gè)“Task”包含若干個(gè)ActivityRecord。AMS用TaskRecord確保Activity啟動(dòng)和退出的順序卸勺。

介紹完這些砂沛,我們開(kāi)始進(jìn)入正題

Activity的啟動(dòng)過(guò)程

Activity啟動(dòng)最終會(huì)調(diào)用到startActivityForResult方法,我們只需要關(guān)注mParent == null中的邏輯即可曙求。mParent代表的是ActivityGroup碍庵,其最開(kāi)始是為了在一個(gè)界面中嵌入多個(gè)子Activity,在API13的時(shí)候就已經(jīng)廢棄了悟狱,可以使用Fragment表示一個(gè)界面的多個(gè)區(qū)域静浴。

# android.app.Activity
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                   @Nullable Bundle options) {
    if (mParent == null) {
        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 {
        ...
    }
}

調(diào)用了Instrumentation的execStartActivity方法,在這里通過(guò)ActivityManagerNative.getDefault()方法獲取ActivityManagerService的一個(gè)本地代理對(duì)象ActivityManagerProxy挤渐,然后調(diào)用了其startActivity方法:

# android.app.Instrumentation
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
    try {
       ... 
        int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

我們看一下ActivityManagerNative苹享,繼承了Binder并實(shí)現(xiàn)了IActivityManager接口,ActivityManagerService就是繼承了ActivityManagerNative浴麻。

public abstract class ActivityManagerNative extends Binder implements IActivityManager
public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback
class ActivityManagerProxy implements IActivityManager

ActivityManagerNative實(shí)際上獲取的就是其內(nèi)部類ActivityManagerProxy對(duì)象得问。ActivityManagerProxy只是ActivityManagerService的本地代理對(duì)象,其startActivity方法會(huì)調(diào)用到AMS的startActivity方法软免。而且要注意宫纬,這個(gè)startActivity方法會(huì)把ApplicationThread對(duì)象傳遞到AMS所在進(jìn)程,當(dāng)然了AMS拿到的實(shí)際上是ApplicationThread的代理對(duì)象ApplicationThreadProxy膏萧,AMS就要通過(guò)這個(gè)代理對(duì)象與我們的App進(jìn)程進(jìn)行通信漓骚。

# android.app.ActivityManagerNative
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }

    return new ActivityManagerProxy(obj);
}

static public IActivityManager getDefault() {
    return gDefault.get();
}

注:在Android8.0,由于使用AIDL的方式來(lái)寫ActivityManagerService榛泛,ActivityManagerNative已經(jīng)過(guò)期蝌蹂。

我們接著看一下AMS的startActivity方法:

# com.android.server.am.ActivityManagerService
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());
}

startActivity方法緊接著調(diào)用了其startActivityAsUser方法。

@Override
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) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
}

接著調(diào)用了ActivityStarter的startActivityMayWait方法曹锨,由于方法很長(zhǎng)孤个,我們只保留關(guān)鍵的流程部分:

# com.android.server.am.ActivityStarter
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) {
   
        ...
        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);

         ...
    }
}

ActivityStarter調(diào)用了自身的startActivityLocked方法,這又是一個(gè)很長(zhǎng)的方法艘希,保留關(guān)鍵的流程如下硼身。

# com.android.server.am.ActivityStarter

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;
    ...
    try {
        mService.mWindowManager.deferSurfaceLayout();
        err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true, options, inTask);
    } finally {
        mService.mWindowManager.continueSurfaceLayout();
    }
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
    return err;
}

ActivityStarter又調(diào)用了自身的startActivityUnchecked方法,

# com.android.server.am.ActivityStarter

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    ...
    if (mDoResume) {
        ...
        if (!mTargetStack.isFocusable()
            ...
        } else {
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else {
       ...
    }
    ...
    return START_SUCCESS;
}

在ActivityStarter中調(diào)用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法覆享。

# com.android.server.am.ActivityStackSupervisor

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    ... 
}

在ActivityStackSupervisor的resumeFocusedStackTopActivityLocked中又調(diào)用了ActivityStack的resumeTopActivityUncheckedLocked方法。

# com.android.server.am.ActivityStack

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
   ...
    boolean result = false;
    try {
        // Protect against recursion.
        mStackSupervisor.inResumeTopActivity = true;
        ...
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    return result;
}

ActivityStack在resumeTopActivityUncheckedLocked又調(diào)用了其自身的resumeTopActivityInnerLocked方法营袜。

# com.android.server.am.ActivityStack
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
     ..
    // We need to start pausing the current activity so the top one can be resumed...
    ...
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }
    ...
}

由于當(dāng)前的Activity執(zhí)行了onResume撒顿,所以mResumedActivity != null 條件滿足,就會(huì)調(diào)用startPausingLocked方法先暫停當(dāng)前的Activity荚板。注意:這個(gè)過(guò)程必然是一個(gè)IPC過(guò)程凤壁。我們看一下startPausingLocked方法吩屹。

# com.android.server.am.ActivityStack
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
        ActivityRecord resuming, boolean dontWait) {

    ActivityRecord prev = mResumedActivity;
    ...

    if (prev.app != null && prev.app.thread != null) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
        try {
            ...
            prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                    userLeaving, prev.configChangeFlags, dontWait);
        } catch (Exception e) {
           ...
        }
    } else {
       ...
    }
    ...
}

prev.app.thread表示的是IApplicationThread對(duì)象,在這里就是指的發(fā)起啟動(dòng)的Activity所在進(jìn)程的ApplicationThread的本地代理ApplicationThreadProxy拧抖。調(diào)用它的schedulePauseActivity方法煤搜,很明顯是一次IPC過(guò)程,最終調(diào)用到server端唧席,也就是發(fā)起啟動(dòng)的Activity所在進(jìn)程ApplicationThread的schedulePauseActivity方法擦盾。

# android.app.ActivityThread$$ApplicationThread

public final void schedulePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport) {
    int seq = getLifecycleSeq();
    if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
            + " operation received seq: " + seq);
    sendMessage(
            finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
            token,
            (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
            configChanges,
            seq);
}

通過(guò)Hander的轉(zhuǎn)發(fā),接著會(huì)調(diào)用到ActivityThread的handlePauseActivity方法淌哟。

# android.app.ActivityThread

private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport, int seq) {
    ActivityClientRecord r = mActivities.get(token);
    ...
    if (r != null) {
    ...
        performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
    ...
        // Tell the activity manager we have paused.
        if (!dontReport) {
            try {
                ActivityManagerNative.getDefault().activityPaused(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
        mSomeActivitiesChanged = true;
    }
}

在ActivityThread的handlePauseActivity中迹卢,首先會(huì)調(diào)用performPauseActivity來(lái)暫停當(dāng)前的Activity,經(jīng)過(guò)層層調(diào)用徒仓,會(huì)調(diào)用到Intrumentation的callActivityOnPause方法腐碱,最終調(diào)用Activity的onPause方法,這一塊的流程比較簡(jiǎn)單掉弛,在這里就不再詳細(xì)分析了症见,感興趣的可以自己研究下。

暫停之后殃饿,會(huì)調(diào)動(dòng)ActivityManagerNative.getDefault().activityPaused(token)谋作,這個(gè)很明顯又是一次IPC過(guò)程,就是告訴AMS壁晒,已經(jīng)暫停當(dāng)前的Activity瓷们,可以啟動(dòng)新的Activity 了。

我們來(lái)看一下AMS的的activityPaused方法:

# com.android.server.am.ActivityManagerService
@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);
}

AMS中的activityPaused又調(diào)用了ActivityStack的activityPausedLocked方法秒咐。

# com.android.server.am.ActivityStack

final void activityPausedLocked(IBinder token, boolean timeout) {
    ...
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        if (mPausingActivity == r) {
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                    + (timeout ? " (due to timeout)" : " (pause complete)"));
            completePauseLocked(true, null);
            return;
        } else {
           ...
        }
    }
   ...
}

在這個(gè)方法中又調(diào)用了ActivityStack自身的completePauseLocked方法谬晕,

# com.android.server.am.ActivityStack
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
    ActivityRecord prev = mPausingActivity;
    if (resumeNext) {
        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
        if (!mService.isSleepingOrShuttingDownLocked()) {
            mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
        } else {
           ...
        }
    }
    ...
}

然后又調(diào)用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,這視乎又重新調(diào)用了一遍携取,真復(fù)雜啊攒钳。

這個(gè)流程我們上面講過(guò)了,ActivityStackSupervisor會(huì)繼續(xù)調(diào)用ActivityStack的resumeTopActivityUncheckedLocked方法雷滋,然后ActivityStack又調(diào)用其resumeTopActivityInnerLocked方法不撑,調(diào)來(lái)調(diào)去,又到這個(gè)方法里面了晤斩,上次在這里是執(zhí)行了前一個(gè)Activity的onPause方法焕檬。這次會(huì)調(diào)用到ActivityStackSupersivor的startSpecificActivityLocked方法。

# com.android.server.am.ActivityStack
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    // We need to start pausing the current activity so the top one can be resumed...
    final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }

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

    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
    return true;
}

分析到這里澳泵,好像我們的就要開(kāi)始啟動(dòng)我們的目標(biāo)Activity了实愚,好激動(dòng)有木有!

在ActivityStackSupersivor的startSpecificActivityLocked方法中會(huì)判斷Activity所在進(jìn)程是否存在,如果不存在的話就要?jiǎng)?chuàng)建一個(gè)新的進(jìn)程腊敲。在這里击喂,我們是Activity啟動(dòng)其App內(nèi)部的另一個(gè)Activity,所以進(jìn)程肯定是存在的碰辅,會(huì)走到realStartActivityLocked方法中懂昂。

# com.android.server.am.ActivityStackSupervisor
void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    ... 
    if (app != null && app.thread != null) {
        try {
    ...
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
           ...
        }

    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

再來(lái)看一下ActivityStackSupersivor的realStartActivityLocked方法,這次似乎真的要啟動(dòng)一個(gè)Activity了没宾。

# com.android.server.am.ActivityStackSupervisor

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    try {

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

    } catch (RemoteException e) {
       ...
    }
    ...
    return true;
}

看了代碼凌彬,果然,調(diào)用了app.thread.scheduleLaunchActivity方法榕吼,app.thread我們前面講過(guò)饿序,就是IApplicationThread對(duì)象,實(shí)際上就是ApplicationThreadProxy對(duì)象羹蚣,經(jīng)過(guò)IPC過(guò)程會(huì)調(diào)用到ApplicationThread的scheduleLaunchActivity方法原探,我們來(lái)看一下:

# android.app.ActivityThread$$ApplicationThread
@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) {

    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

通過(guò)Hander的轉(zhuǎn)發(fā),接著會(huì)調(diào)用到ActivityThread的handlePauseActivity方法顽素。

# android.app.ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
    ...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
      ...
    } else {
       ...
    }
}

handlePauseActivity內(nèi)部調(diào)用performLaunchActivity方法:

# android.app.ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
       ...
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, 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);

            ...
            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
           ...
            r.activity = activity;
            r.stopped = true;
            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);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
       ...
    }

    return activity;
}

在performLaunchActivity內(nèi)部咽弦,創(chuàng)建了Activity對(duì)象,并調(diào)用了activity的attach方法胁出,在這個(gè)方法中綁定一些屬性型型,并且創(chuàng)建了Activity所屬的Window對(duì)象。接著Instrumentation會(huì)調(diào)用callActivityOnCreate全蝶、callActivityOnRestoreInstanceState闹蒜、callActivityOnPostCreate等來(lái)完成Activity生命周期的回調(diào)。不過(guò)有一點(diǎn)很有意思抑淫,在這個(gè)方法中Activity自己調(diào)用了其performStart方法绷落,但這個(gè)方法內(nèi)部又調(diào)用了Instrumentation的callActivityOnStart方法,進(jìn)而又調(diào)用了Activity的onStart方法始苇。繞過(guò)來(lái)繞過(guò)去砌烁,總之,Activity生命周期方法的調(diào)用均是通過(guò)Instrumentation來(lái)控制的催式。

至此函喉,Activity的啟動(dòng)過(guò)程算是分析完了,太費(fèi)腦筋了荣月,需要來(lái)一瓶營(yíng)養(yǎng)快線補(bǔ)補(bǔ)身體管呵。流程太多,不好記哺窄,但是有句話說(shuō)的好 "一圖勝千言"撇寞,下面我們來(lái)看一下Activity啟動(dòng)的一個(gè)時(shí)序圖顿天。

Activity啟動(dòng)過(guò)程.png

總結(jié)

源碼分析過(guò)程是比較繞堂氯,比較燒腦的過(guò)程蔑担,不要太糾結(jié)去API的調(diào)用,盡量側(cè)重流程咽白。分析源碼啤握,最好帶著問(wèn)題去分析,不要為了分析而分析晶框,盡量在分析過(guò)程中尋找自己想要的答案排抬。比如:

  • Activity對(duì)象是怎么創(chuàng)建的?
  • Window對(duì)象是什么時(shí)候創(chuàng)建的授段?
  • LayoutInflater什么時(shí)候創(chuàng)建的蹲蒲?
  • 為什么在Activity中的布局中或者Fragment的中View獲取的Context都是其所在的Activity對(duì)象?
  • 為什么自定義View一定要有兩個(gè)參數(shù)的構(gòu)造函數(shù)侵贵?
  • Activity的生命周期方法是被誰(shuí)回調(diào)的届搁?
  • Application是什么時(shí)候創(chuàng)建的?
  • ClassLoader對(duì)象是什么時(shí)候創(chuàng)建的窍育?
  • 子線程可以啟動(dòng)Activity卡睦、Service嗎?
  • 下拉通知欄漱抓,會(huì)影響Activity生命周期嗎表锻?

筆者初入Android開(kāi)發(fā)沒(méi)多久的時(shí)候,有次面試乞娄,面試官問(wèn)我在子線程中啟動(dòng)Activity可以嗎瞬逊?我回答可以,因?yàn)槲以囘^(guò)仪或,但是問(wèn)我為什么我卻不知道确镊。如果那時(shí)候看了Activity啟動(dòng)過(guò)程的源碼,看了Binder機(jī)制的話溶其,應(yīng)該很容易的就回答出來(lái)了骚腥。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瓶逃,隨后出現(xiàn)的幾起案子束铭,更是在濱河造成了極大的恐慌,老刑警劉巖厢绝,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件契沫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡昔汉,警方通過(guò)查閱死者的電腦和手機(jī)懈万,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人会通,你說(shuō)我怎么就攤上這事口予。” “怎么了涕侈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵沪停,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我裳涛,道長(zhǎng)木张,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任端三,我火速辦了婚禮舷礼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郊闯。我一直安慰自己妻献,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布虚婿。 她就那樣靜靜地躺著旋奢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪然痊。 梳的紋絲不亂的頭發(fā)上至朗,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音剧浸,去河邊找鬼锹引。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唆香,可吹牛的內(nèi)容都是我干的嫌变。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼躬它,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼腾啥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起冯吓,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤倘待,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后组贺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凸舵,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年失尖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了啊奄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渐苏。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菇夸,靈堂內(nèi)的尸體忽然破棺而出琼富,到底是詐尸還是另有隱情,我是刑警寧澤峻仇,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布公黑,位于F島的核電站伙窃,受9級(jí)特大地震影響荣德,放射性物質(zhì)發(fā)生泄漏袁波。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一吭从、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恶迈,春花似錦涩金、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至奈附,卻和暖如春全度,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背斥滤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工将鸵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佑颇。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓顶掉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親挑胸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痒筒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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