Activity启动流程

一直都想过要去看一看一个activity是怎么启动起来的,但一直都没有静下心去认真看一看,现在趁着有时间好好阅读了一下源码,加上网上一些同志的分享,终于吧代码撸的比较清楚了,怕时间一久,又忘记了,赶紧记下来,如果有什么错误和遗漏的话,看官们也请指出。(本文中源码出自Android API 23)

首先我们打开activity的startActivity方法:

@Overridepublic void startActivity(Intent intent) {    mBase.startActivity(intent);}

Activity 继承于 Context ,这是个抽象类,里面并没有实现 startActivity() 这个方法,查了一下它的子类,嗯哼,就看了 ContextWrapper 实现了它,但是,这个 mBase 又是什么鬼?嗯,也是一个 Context 对象,但具体是那个类呢,查了一下 Context 的继承关系,找到了 ContentImpl 这个类,看一下这个类的介绍:

/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */class ContextImpl extends Context {...}

这个类就是Context的Api的共同的实现类了,上面说到的 mBase 对象实际上说的就是这个类的实例了,那么这个对象是怎么来的,啥时候实例化的?不急,往下看,迟早要知道的。

好了,现在来看一下 ContentImpl 中 startActivity() 的实现:

@Overridepublic void startActivity(Intent intent) {    warnIfCallingFromSystemProcess();    startActivity(intent, null);}
@Overridepublic void startActivity(Intent intent, Bundle options) {    warnIfCallingFromSystemProcess();    if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {        throw new AndroidRuntimeException(                "Calling startActivity() from outside of an Activity "                + " context requires the FLAG_ACTIVITY_NEW_TASK flag."                + " Is this really what you want?");    }    mMainThread.getInstrumentation().execStartActivity(            getOuterContext(), mMainThread.getApplicationThread(), null,            (Activity) null, intent, -1, options);}

看红色代码部分,mMainThread 就是 ActivityThread 类的实例,整个app进程的入口main()函数也是在这个类中的,这个 mMainThread 提供了一个 Instrumentation 对象

/** * Base class for implementing application instrumentation code.  When running * with instrumentation turned on, this class will be instantiated for you * before any of the application code, allowing you to monitor all of the * interaction the system has with the application.  An Instrumentation * implementation is described to the system through an AndroidManifest.xml‘s * <instrumentation> tag. */public class Instrumentation {...}

简单的说,它就是用来监控应用中各种交互行为,从注释上看,我们可以通过 Manifest 来指定一个我们自己实现的 Instrumentation 类,好了这个不是重点,让我们看一下一个类怎么 startActivity 的吧:

public ActivityResult execStartActivity(        Context who, IBinder contextThread, IBinder token, Activity target,        Intent intent, int requestCode, Bundle options) {    //...    //前面的不是重点

    try {        intent.migrateExtraStreamToClipData();        intent.prepareToLeaveProcess();        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;}

好吧,怎么这家伙又把启动 activity 的事情交给别人做了。。。再点进去看:咦,怎么。。怎么是 IActivityManager 的接口方法,好吧,又要找它的实现类了,but 貌似找到的这个家伙 ActivityManagerProxy 并没有认真的做事情啊,它找了一个代理去 startActivity()去了,那我们就去找这个代理去,从 IActivityManager extends IInterface 这个类的继承方式我们就能发现这其实就是Android中的Binder机制,跨进程的通信机制,ActivityManagerProxy 找的代理其实就是 ActivityManagerService ActivityManagerService 属于系统进程,它对手机中所有的activity进行了统一的管理,源码中就是这么个获取的:

IBinder b = ServiceManager.getService("activity");IActivityManager am = asInterface(b);

熟悉的 aidl 嘛,好了好了,感觉有点跑偏,往回扯,来看看 AMS 怎么实现 startActivity() 的:

@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,        int startFlags, ProfilerInfo profilerInfo, Bundle options) {    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,        resultWho, requestCode, startFlags, profilerInfo, options,        UserHandle.getCallingUserId());}

@Overridepublic final int startActivityAsUser(IApplicationThread caller, String callingPackage,        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,        int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {    enforceNotIsolatedCaller("startActivity");    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,            false, ALLOW_FULL_ONLY, "startActivity", null);    // TODO: Switch to user app stacks here.    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,            profilerInfo, null, null, options, false, userId, null, null);}

找到了,一个 mStackSupervisor 对象,这又是干啥的?字面上的意思就是活动栈的管理器,先不管了,让我们先看看它的实现(...啊,代码不是一般的长,咱们只划重点):

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, WaitResult outResult, Configuration config,        Bundle options, boolean ignoreTargetSecurity, int userId,        IActivityContainer iContainer, TaskRecord inTask) {    // Refuse possible leaked file descriptors    if (intent != null && intent.hasFileDescriptors()) {        throw new IllegalArgumentException("File descriptors passed in Intent");    }    boolean componentSpecified = intent.getComponent() != null;

    // Don‘t modify the client‘s object!    intent = new Intent(intent);

    // Collect information about the target of the Intent.    ActivityInfo aInfo =            resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

    ActivityContainer container = (ActivityContainer)iContainer;    synchronized (mService) {        if (container != null && container.mParentActivity != null &&                container.mParentActivity.state != RESUMED) {            // Cannot start a child activity if the parent is not resumed.            return ActivityManager.START_CANCELED;        }        final int realCallingPid = Binder.getCallingPid();        final int realCallingUid = Binder.getCallingUid();        int callingPid;        if (callingUid >= 0) {            callingPid = -1;        } else if (caller == null) {            callingPid = realCallingPid;            callingUid = realCallingUid;        } else {            callingPid = callingUid = -1;        }

        final ActivityStack stack;        if (container == null || container.mStack.isOnHomeDisplay()) {            stack = mFocusedStack;        } else {            stack = container.mStack;        }        stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;        if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,                "Starting activity when config will change = " + stack.mConfigWillChange);

        final long origId = Binder.clearCallingIdentity();

        if (aInfo != null &&                (aInfo.applicationInfo.privateFlags                        &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {            // This may be a heavy-weight process!  Check to see if we already            // have another, different heavy-weight process running.            if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {                if (mService.mHeavyWeightProcess != null &&                        (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||                        !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {                    int appCallingUid = callingUid;                    if (caller != null) {                        ProcessRecord callerApp = mService.getRecordForAppLocked(caller);                        if (callerApp != null) {                            appCallingUid = callerApp.info.uid;                        } else {                            Slog.w(TAG, "Unable to find app for caller " + caller                                  + " (pid=" + callingPid + ") when starting: "                                  + intent.toString());                            ActivityOptions.abort(options);                            return ActivityManager.START_PERMISSION_DENIED;                        }                    }

                    IIntentSender target = mService.getIntentSenderLocked(                            ActivityManager.INTENT_SENDER_ACTIVITY, "android",                            appCallingUid, userId, null, null, 0, new Intent[] { intent },                            new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT                            | PendingIntent.FLAG_ONE_SHOT, null);

                    Intent newIntent = new Intent();                    if (requestCode >= 0) {                        // Caller is requesting a result.                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,                            new IntentSender(target));                    if (mService.mHeavyWeightProcess.activities.size() > 0) {                        ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,                                hist.packageName);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,                                hist.task.taskId);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,                            aInfo.packageName);                    newIntent.setFlags(intent.getFlags());                    newIntent.setClassName("android",                            HeavyWeightSwitcherActivity.class.getName());                    intent = newIntent;                    resolvedType = null;                    caller = null;                    callingUid = Binder.getCallingUid();                    callingPid = Binder.getCallingPid();                    componentSpecified = true;                    try {                        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);                    } catch (RemoteException e) {                        aInfo = null;                    }                }            }        }

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

        Binder.restoreCallingIdentity(origId);

        if (stack.mConfigWillChange) {            // If the caller also wants to switch to a new configuration,            // do so now.  This allows a clean switch, as we are waiting            // for the current activity to pause (so we will not destroy            // it), and have not yet started the next activity.            mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,                    "updateConfiguration()");            stack.mConfigWillChange = false;            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,                    "Updating to new configuration after starting activity.");            mService.updateConfigurationLocked(config, null, false, false);        }

        if (outResult != null) {            outResult.result = res;            if (res == ActivityManager.START_SUCCESS) {                mWaitingActivityLaunched.add(outResult);                do {                    try {                        mService.wait();                    } catch (InterruptedException e) {                    }                } while (!outResult.timeout && outResult.who == null);            } else if (res == ActivityManager.START_TASK_TO_FRONT) {                ActivityRecord r = stack.topRunningActivityLocked(null);                if (r.nowVisible && r.state == RESUMED) {                    outResult.timeout = false;                    outResult.who = new ComponentName(r.info.packageName, r.info.name);                    outResult.totalTime = 0;                    outResult.thisTime = 0;                } else {                    outResult.thisTime = SystemClock.uptimeMillis();                    mWaitingActivityVisible.add(outResult);                    do {                        try {                            mService.wait();                        } catch (InterruptedException e) {                        }                    } while (!outResult.timeout && outResult.who == null);                }            }        }

        return res;    }}

继续往里走~~

final int startActivityLocked(IApplicationThread caller,        Intent intent, String resolvedType, ActivityInfo aInfo,        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,        IBinder resultTo, String resultWho, int requestCode,        int callingPid, int callingUid, String callingPackage,        int realCallingPid, int realCallingUid, int startFlags, Bundle options,        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,        ActivityContainer container, TaskRecord inTask) {    int err = ActivityManager.START_SUCCESS;

    //...    //中间各种逻辑判断,这里就不贴出来了,贼多。。。我们依旧划个重点

    doPendingActivityLaunchesLocked(false);

    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,            startFlags, true, options, inTask);//这里记住一下倒数第3个参数是true。

    if (err < 0) {        // If someone asked to have the keyguard dismissed on the next        // activity start, but we are not actually doing an activity        // switch...  just dismiss the keyguard now, because we        // probably want to see whatever is behind it.        notifyActivityDrawnForKeyguard();    }    return err;}

还得往里走。。。好多层:

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,        boolean doResume, Bundle options, TaskRecord inTask) {    //前面N个判断...

    mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,            intent, r.getUriPermissionsLocked(), r.userId);

    if (sourceRecord != null && sourceRecord.isRecentsActivity()) {        r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);    }    if (newTask) {        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);    }    ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);    targetStack.mLastPausedActivity = null;    targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);    if (!launchTaskBehind) {        // Don‘t set focus on an activity that‘s going to the back.        mService.setFocusedActivityLocked(r, "startedActivity");    }    return ActivityManager.START_SUCCESS;}

这个方法就屌的不行了,好几百行,一行行看下来绝对的心力交瘁,换个角度来看,这个方法的返回值比较有特点,他们都是 ActiviyManager 中的常量,让我们看一看这些常量代表的意思:

/** * Result for IActivityManaqer.startActivity: the activity was started * successfully as normal. * @hide */public static final int START_SUCCESS = 0;

/** * Result for IActivityManaqer.startActivity: the caller asked that the Intent not * be executed if it is the recipient, and that is indeed the case. * @hide */public static final int START_RETURN_INTENT_TO_CALLER = 1;

/** * Result for IActivityManaqer.startActivity: activity wasn‘t really started, but * a task was simply brought to the foreground. * @hide */public static final int START_TASK_TO_FRONT = 2;

/** * Result for IActivityManaqer.startActivity: activity wasn‘t really started, but * the given Intent was given to the existing top activity. * @hide */public static final int START_DELIVERED_TO_TOP = 3;

好了,就贴几个,可以看出这些都是我们启动以后 activity 的返回的各种结果,可想而知前面的各种逻辑是干嘛的了。那么这样我们就只找成功的那一个常量值 START_SUCCESS,在 startActivityLocked() 我们发现之后方法末尾返回了 START_SUCCESS,其余都不是,那么关键代码也就比较好找了,请看上面红色的重点~~,好了继续走你,这回就来到了 ActivityStack 这个类了:

final void startActivityLocked(ActivityRecord r, boolean newTask,        boolean doResume, boolean keepCurTransition, Bundle options) {    //逻辑判断。。比如Home键什么的

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

还记得前面划重点的参数吧,就是doResume,前面的一些逻辑代码咱们就不谈了,有兴趣的小盆友有时间可以慢慢看,咱们继续往下走 ActivityStackSupervisor.resumeTopActivitiesLocked():

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,        Bundle targetOptions) {    if (targetStack == null) {        targetStack = mFocusedStack;    }    // Do targetStack first.    boolean result = false;    if (isFrontStack(targetStack)) {        result = targetStack.resumeTopActivityLocked(target, targetOptions);    }

    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 ActivityStack stack = stacks.get(stackNdx);            if (stack == targetStack) {                // Already started above.                continue;            }            if (isFrontStack(stack)) {                stack.resumeTopActivityLocked(null);            }        }    }    return result;}

这个方法代码量比较少,关键的地方就是 resumeTopActivityLocked 了,感觉越来越接近目标了,还有点小激动。。。ActivityStack.resumeTopActivityLocked():

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {    if (mStackSupervisor.inResumeTopActivity) {        // Don‘t even start recursing.        return false;    }

    boolean result = false;    try {        // Protect against recursion.        mStackSupervisor.inResumeTopActivity = true;        if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {            mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;            mService.updateSleepIfNeededLocked();        }        result = resumeTopActivityInnerLocked(prev, options);    } finally {        mStackSupervisor.inResumeTopActivity = false;    }    return result;}

嗯,是一个内部具体实现方法:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {      //.....    ActivityStack lastStack = mStackSupervisor.getLastStack();    if (next.app != null && next.app.thread != null) {

            //.........        try {                        //...........                   } catch (Exception e) {            // Whoops, need to restart this activity!            if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "                    + lastState + ": " + next);            next.state = lastState;            if (lastStack != null) {                lastStack.mResumedActivity = lastResumedActivity;            }            Slog.i(TAG, "Restarting because process died: " + next);            if (!next.hasBeenLaunched) {                next.hasBeenLaunched = true;            } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&                    mStackSupervisor.isFrontStack(lastStack)) {                mWindowManager.setAppStartingWindow(                        next.appToken, next.packageName, next.theme,                        mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),                        next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,                        next.windowFlags, null, true);            }            mStackSupervisor.startSpecificActivityLocked(next, true, false);            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();            return true;        }

        // From this point on, if something goes wrong there is no way        // to recover the activity.        try {            next.visible = true;            completeResumeLocked(next);        } catch (Exception e) {            // If any exception gets thrown, toss away this            // activity and try the next one.            Slog.w(TAG, "Exception thrown during resume of " + next, e);            requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,                    "resume-exception", true);            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();            return true;        }        next.stopped = false;

    } else {        // Whoops, need to restart this activity!        if (!next.hasBeenLaunched) {            next.hasBeenLaunched = true;        } else {            if (SHOW_APP_STARTING_PREVIEW) {                mWindowManager.setAppStartingWindow(                        next.appToken, next.packageName, next.theme,                        mService.compatibilityInfoForPackageLocked(                                next.info.applicationInfo),                        next.nonLocalizedLabel,                        next.labelRes, next.icon, next.logo, next.windowFlags,                        null, true);            }            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);        }        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);        mStackSupervisor.startSpecificActivityLocked(next, true, true);    }

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

阿西吧,将近400行。。老衲差点就要圆寂在这源码上面了。。耐着性子看了好几遍,还是让老衲找出了重点,前面的判断大概都有比如从 activity 后台到前台,从暂停到恢复,回到home页,屏幕旋转,切换到不同栈 activity 等等各种情况,但是这个不是咱们要的,咱就是要一个 activity 从无到有,所以咱只留相关的代码,ActivityStackSupervisor.startSpecificActivityLocked():

void startSpecificActivityLocked(ActivityRecord r,        boolean andResume, boolean checkConfig) {    // Is this activity‘s application already running?    ProcessRecord app = mService.getProcessRecordLocked(r.processName,            r.info.applicationInfo.uid, true);

    r.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {        try {            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0                    || !"android".equals(r.info.packageName)) {                // Don‘t add this if it is a platform component that is marked                // to run in multiple processes, because this is actually                // part of the framework so doesn‘t make sense to track as a                // separate apk in the process.                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,                        mService.mProcessStats);            }            realStartActivityLocked(r, app, andResume, checkConfig);            return;        } catch (RemoteException e) {            Slog.w(TAG, "Exception when starting activity "                    + r.intent.getComponent().flattenToShortString(), e);        }

        // If a dead object exception was thrown -- fall through to        // restart the application.    }

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

啊,终于找到一个比较少代码的方法了,从逻辑判断上看 realStartActivityLocked 才是开启我们应用内的方法嘛,至于 startProcessLocked,它是启动应用进程的,咱们先不管,下一篇文章再理它,看看 realStartActivityLocked 怎么个实现的:

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

    //...check..    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);

    // do other things...    return true;}

忽略掉其他的代码,我们只看重点,这个 thread 是谁呢?还记得我们的 ActivityThread 吧,这个thread其实就是 ActivityThread 中的内部类对象 ApplicationThread ,我们去看一下这个方法的实现,看了那么多代码,这里其实已经很接近了:

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

唔,找一下LAUNCH_ACTIVITY这个常量,最终执行了handlerLaunchActivity():

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        }    }}

走进科学~~performLaunchActivity():

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {    // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

    ActivityInfo aInfo = r.activityInfo;    if (r.packageInfo == null) {        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,                Context.CONTEXT_INCLUDE_CODE);    }

    ComponentName component = r.intent.getComponent();    if (component == null) {        component = r.intent.resolveActivity(            mInitialApplication.getPackageManager());        r.intent.setComponent(component);    }

    if (r.activityInfo.targetActivity != null) {        component = new ComponentName(r.activityInfo.packageName,                r.activityInfo.targetActivity);    }

    Activity activity = null;    try {        java.lang.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);        }    } catch (Exception e) {        if (!mInstrumentation.onException(activity, e)) {            throw new RuntimeException(                "Unable to instantiate activity " + component                + ": " + e.toString(), e);        }    }

    try {        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);        if (localLOGV) Slog.v(                TAG, r + ": app=" + app                + ", appName=" + app.getPackageName()                + ", pkg=" + r.packageInfo.getPackageName()                + ", comp=" + r.intent.getComponent().toShortString()                + ", dir=" + r.packageInfo.getAppDir());

        if (activity != null) {            Context appContext = createBaseContextForActivity(r, activity);            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());            Configuration config = new Configuration(mCompatConfiguration);            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "                    + r.activityInfo.name + " with config " + config);            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);

            if (customIntent != null) {                activity.mIntent = customIntent;            }            r.lastNonConfigurationInstances = null;            activity.mStartedActivity = false;            int theme = r.activityInfo.getThemeResource();            if (theme != 0) {                activity.setTheme(theme);            }

            activity.mCalled = false;            if (r.isPersistable()) {                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);            } else {                mInstrumentation.callActivityOnCreate(activity, r.state);            }            if (!activity.mCalled) {                throw new SuperNotCalledException(                    "Activity " + r.intent.getComponent().toShortString() +                    " did not call through to super.onCreate()");            }            r.activity = activity;            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) {        if (!mInstrumentation.onException(activity, e)) {            throw new RuntimeException(                "Unable to start activity " + component                + ": " + e.toString(), e);        }    }

    return activity;}

哇哇哇,满屏的亲切感啊,通过反射创建了一个 Activity 的实例,然后使用 Instrumentation 执行 onCreate 部分,还有那个最初让我们疑惑的 ContextImpl 对象,用 attach 关联了起来,这里都一一给出了答案。。感觉very nice啊。。。

好了流程就说到这里了,下次再说一下应用程序的启动流程...看官们要是有看到不对的地方,请指正,请大力打脸。。。同求进步。。。。

时间: 2024-08-10 17:28:01

Activity启动流程的相关文章

Cocos2d-x3.3RC0的Android编译Activity启动流程分析

本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXV4aWt1b18x/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > watermark/2/text/aHR0cDov

android源码解析之(十四)--&gt;Activity启动流程

好吧,终于要开始讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍: An activity represents a single screen with a user interface. For example, an email appl

深入理解Activity启动流程(四)–Activity Task的调度算法

本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启动的概要流程 深入理解Activity启动流程(二)--Activity启动相关类的类图 深入理解Activity启动流程(三)--Activity启动的详细流程1 深入理解Activity启动流程(三)--Activity启动的详细流程2 前面两篇博客介绍了Activity的详细启动流程,提到ActivityStack类的startActivityU

&lt;转&gt;深入理解Activity启动流程(一)–Activity启动的概要流程

本文原创作者:Cloud Chou. 原文地址:http://www.cloudchou.com/android/post-788.html Android中启动某个Activity,将先启动Activity所在的应用.应用启动时会启动一个以应用包名为进程名的进程,该进程有一个主线程,叫ActivityThread,也叫做UI线程. 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(二)--Activity启动相关类的类图 深

&lt;转&gt;深入理解Activity启动流程(二)–Activity启动相关类的类图

本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先为大家介绍Activity启动时涉及到的类,这样大家可以有大概的了解,不至于在细节中迷失. 深入理解Activity启动流程(一)--Activity启动的概要流程 深入理解Activity启动流程(三)--Activity启动的详细流程1 深入理解Activity启动流程(三)--Activity启动的详细流程2

图解Activity启动流程

前言 基于android4.4.2源码 activity 生命周期图 本文在讲诉Activity启动流程涉及到了一些Activity生命周期的知识,所以把官方文档直接贴上来(图1),对Activity生命周期知识了然于心的大神直接无视就好.对于刚接触android的看客,则需要先去了解这方面的知识. 涉及知识 binder机制,因本人原因只能在后续的文章才会更新这方面的内容,对这方面不了解的看客建议先去看binder机制的知识. android Task ,官方文档解释很清楚. 图1 一.Act

深入理解Activity启动流程(二)–Activity启动相关类的类图

本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先为大家介绍Activity启动时涉及到的类,这样大家可以有大概的了解,不至于在细节中迷失. 深入理解Activity启动流程(一)--Activity启动的概要流程 深入理解Activity启动流程(三)--Activity启动的详细流程1 深入理解Activity启动流程(三)--Activity

[Android][Framework]Activity启动流程

开始 从Launcher点击一个App图标,会触发如下动作: LauncherActivity.java protected void (ListView l, View v, int position, long id) { Intent intent = intentForPosition(position); startActivity(intent);} 走到了 Activity.java 的startActivity相关方法: public void startActivity(Int

庖丁解牛 Activity 启动流程

前言 这是 Android 9.0 AOSP 系列 的第五篇了,先来回顾一下前面几篇的大致内容. Java 世界的盘古和女娲 -- Zygote 主要介绍了 Android 世界的第一个 Java 进程 Zygote 的启动过程. 注册服务端 socket,用于响应客户端请求 各种预加载操作,类,资源,共享库等 强制 GC 一次 fork SystemServer 进程 循环等待客户端发来的 socket 请求(请求 socket 连接和请求 fork 应用进程) Zygote家的大儿子 --