IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Activity启动过程分析 -> 正文阅读

[移动开发]Android Activity启动过程分析

当我们在一个Activity中(或通过Context对象),调用startActivity()方法来启动另一个Activity的过程中发生了什么呢?这就是本文想跟大家分享的内容,我们一起通过源码的方式来看下Activity的启动过程。(本文是基于Android Q的源码)

?Activity的启动流程大体分为两步:找到要启动的Activity;然后启动它。(虽说有点像如何把大象装进冰箱,但也确实是那么回事,只不过每个步骤有更多细节)

找到Activity

?要想启动一个Activity,系统先要找到这个Activity的信息。我们以从一个Activity中启动另一个Activity为起点来分析Activity的启动过程,在这个过程种会涉及到系统查找要启动的Activity的过程,下面我们以时序图来分析Activity的启动过程:
在这里插入图片描述
? 这只是Activity启动过程种的一小部分,Activity的启动的服务端是由ActivityTaskManagerService实现的,在ActivityTaskManagerService中Activity的启动又是由ActivityStarter来实现。对于系统如何找到要启动的Activity,大体分为两步:

  • 得到ResolveInfo对象,实现方式是通过ActivityStackSuperVisor.resolveIntent()方法(最终是调用了PackageManagerService.resolveIntent()方法)解析而来;
  • 得到ActivityInfo对象,在得到ResolveInfo对象后,加上一些逻辑判断得到ActivityInfo对象;至此系统就找到了需要启动的Activity;

而这两步都是在ActivityStarter.startActivityMayWait()方法中完成。

//ActivityStarter.java
private int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
        Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
        IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
        Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
        int userId, TaskRecord inTask, String reason,
        boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    // Refuse possible leaked file descriptors
    // 省略部分代码....

    // Save a copy in case ephemeral needs it
    final Intent ephemeralIntent = new Intent(intent);
    // Don't modify the client's object!
    intent = new Intent(intent);
    if (componentSpecified
            && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
            && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && mService.getPackageManagerInternalLocked()
                    .isInstantAppInstallerComponent(intent.getComponent())) {
        intent.setComponent(null /*component*/);
        componentSpecified = false;
    }
    // 通过ActivitySuperVisor.resolveIntent()方法解析得到ResolveInfo对象;
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, mRequest.filterCallingUid));
    if (rInfo == null) {
        UserInfo userInfo = mSupervisor.getUserInfo(userId);
        if (userInfo != null && userInfo.isManagedProfile()) {
            UserManager userManager = UserManager.get(mService.mContext);
            boolean profileLockedAndParentUnlockingOrUnlocked = false;
            long token = Binder.clearCallingIdentity();
            try {
                UserInfo parent = userManager.getProfileParent(userId);
                profileLockedAndParentUnlockingOrUnlocked = (parent != null)
                        && userManager.isUserUnlockingOrUnlocked(parent.id)
                        && !userManager.isUserUnlockingOrUnlocked(userId);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            if (profileLockedAndParentUnlockingOrUnlocked) {
                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, mRequest.filterCallingUid));
            }
        }
    }
    //得到ActivityInfo对象
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

    synchronized (mService.mGlobalLock) {
        final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
        stack.mConfigWillChange = globalConfig != null
                && mService.getGlobalConfiguration().diff(globalConfig) != 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 &&
                mService.mHasHeavyWeightFeature) {
            // 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)) {
                final WindowProcessController heavy = mService.mHeavyWeightProcess;
                if (heavy != null && (heavy.mInfo.uid != aInfo.applicationInfo.uid
                        || !heavy.mName.equals(aInfo.processName))) {
                    int appCallingUid = callingUid;
                    if (caller != null) {
                        WindowProcessController callerApp =
                                mService.getProcessController(caller);
                        if (callerApp != null) {
                            appCallingUid = callerApp.mInfo.uid;
                        } else {
                            Slog.w(TAG, "Unable to find app for caller " + caller
                                    + " (pid=" + callingPid + ") when starting: "
                                    + intent.toString());
                            SafeActivityOptions.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));
                    heavy.updateIntentForHeavyWeightActivity(newIntent);
                    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;
                    rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
                            0 /* matchFlags */, computeResolveFilterUid(
                                    callingUid, realCallingUid, mRequest.filterCallingUid));
                    aInfo = rInfo != null ? rInfo.activityInfo : null;
                    if (aInfo != null) {
                        aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
                    }
                }
            }
        }

        final ActivityRecord[] outRecord = new ActivityRecord[1];
        int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                allowBackgroundActivityStart);

        Binder.restoreCallingIdentity(origId);
        //省略部分代码

        return res;
    }
}

启动Activity

?在了解系统怎么找到要启动的Activity后,我们现在就来看下启动Activity的过程。在了解Activity启动过程前,我们先了解下Activity 栈结构模型

Activity结构模型

下面这幅图就是Activity(对应图中的ActivityRecord)在历史任务中的结构。
在这里插入图片描述

数据结构描述

  • RootActivityContainer : Activity 容器的根节点
  • ActivityDisplay:每个实例代表系统中的一个显示屏幕,也就是说如果你的Android设备是多屏的,那么将会有多个ActivityDisplay实例。
  • ActivityStack: Activity栈,用于表示管理栈中的Activity。
  • TaskRecord:ActivityRecord列表的封装类,在ActivityStack中用于记录历史运行的Activity。
  • ActivityRecord:ActivityRecord表示历史运行的Activity对象。
  • 通过dumpsys activity a命令可查看当前设备的activity栈结构。

启动过程分析

对于上面的数据结构图,要有个基本掌握,这有助于我们理解Activity启动过程中的逻辑。我们先从ActivityStarter.startActivity()方法分析

//ActivityStarter.java
private int startActivity(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,
        SafeActivityOptions options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
            = options != null ? options.popAppVerificationBundle() : null;

    WindowProcessController callerApp = null;
    if (caller != null) {
        callerApp = mService.getProcessController(caller);
        if (callerApp != null) {
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller
                    + " (pid=" + callingPid + ") when starting: "
                    + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }

    final int userId = aInfo != null && aInfo.applicationInfo != null
            ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

    if (err == ActivityManager.START_SUCCESS) {
        Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                + "} from uid " + callingUid);
    }

    ActivityRecord sourceRecord = null;
    //resultRecord用于记录接收启动Activity的结果(要记住这个方法是从Activity.startActivityForResult()调用下来的)
    ActivityRecord resultRecord = null;
    //这里的resultTo取决于是否是Activity(Activity中重写了Context.startActivity()方法)对象启动,
    //如果是Activity则resulTo为该Activity在Activity栈中的ActivityRecord实例,否则为null
    if (resultTo != null) {
        //如果在ActivityA 中启动ActivityB,那么这个sourceRecord实际上就是ActivityA在Activity栈中的ActivityRecord实例;
        sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                "Will send result to " + resultTo + " " + sourceRecord);
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }

    //......省略部分ActivityInfo和权限判断代码......
    
    //创建ActivityRecord对象
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
            mSupervisor, checkedOptions, sourceRecord);
    if (outActivity != null) {
        outActivity[0] = r;
    }

    if (r.appTimeTracker == null && sourceRecord != null) {
        // If the caller didn't specify an explicit time tracker, we want to continue
        // tracking under any it has.
        r.appTimeTracker = sourceRecord.appTimeTracker;
    }

    final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();

    // If we are starting an activity that is not from the same uid as the currently resumed
    // one, check whether app switches are allowed.
    if (voiceSession == null && (stack.getResumedActivity() == null
            || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
            if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                        sourceRecord, startFlags, stack, callerApp));
            }
            ActivityOptions.abort(checkedOptions);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }

    mService.onStartActivitySetDidAppSwitch();
    mController.doPendingActivityLaunches(false);
    //调用另一个startActivity重载方法,该方法会调用startActivityUnchecked()方法。
    final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
    return res;
}

?在此方法中主要完成以下事情:

  • 要启动的Activity包名类名是否存在以及权限的判断;

  • 创建要启动的Activity所对应的ActivityRecord对象

?接下来,我们看下startActivityUnchecked()方法,这个方法很长也很复杂,我们把Activity启动分为以下几种情况来分析:

  • 将Activity加入到现有的TaskRecord中,且Activity栈中已经有要启动的Activity对应的ActivityRecord对象;

  • 将Activity加入到现有的TaskRecord中,但Activity栈中没有要启动的Activity对应的ActivityRecord对象;

  • 加入到新创建的TaskRecord中。

    我们先看第一种方式:

//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity, boolean restrictedBgActivity) {
    //重置变量并重新给mStartActivity,mIntent,mSourceRecord等变量赋值
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor, restrictedBgActivity);

    final int preferredWindowingMode = mLaunchParams.mWindowingMode;
    //计算得到LaunchFlag,并将结果赋值给mLaunchFlag; Flag定义见Intent.Flags注解
    computeLaunchingTaskFlags();
    //计算mSourceRecord所在的ActivityStack,并将得到的结果赋值给mSourceStack变量
    computeSourceStack();
    mIntent.setFlags(mLaunchFlags);
    //getReusableIntentActivity()方法主要是判断要启动的Activity对应的ActivityRecord对象是否可以放入已有的TaskRecord中,
    //如果可以则遍历RootActivityContainer看要启动的Activity对应的ActivityRecord是否已经存在,如果存在则返回这个对象;
    //如果不存在则返要放入的TaskRecord中的顶层ActivityRecord
    ActivityRecord reusedActivity = getReusableIntentActivity();

    mSupervisor.getLaunchParamsController().calculate(
            reusedActivity != null ? reusedActivity.getTaskRecord() : mInTask,
            r.info.windowLayout, r, sourceRecord, options, PHASE_BOUNDS, mLaunchParams);
    mPreferredDisplayId =
            mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
                    : DEFAULT_DISPLAY;

    if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info,
            mPreferredDisplayId, true /* allowInstrumenting */)) {
        Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
        return START_CANCELED;
    }
    
    if (reusedActivity != null) {
        if (mService.getLockTaskController().isLockTaskModeViolation(
                reusedActivity.getTaskRecord(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        // True if we are clearing top and resetting of a standard (default) launch mode
        // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
        // 如果launchMode为standard,且intent flag设置了FLAG_ACTIVITY_CLEAR_TOP或FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,
        // 则clearTopAndResetStandardLaunchMode为true
        final boolean clearTopAndResetStandardLaunchMode =
                (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
                        == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                && mLaunchMode == LAUNCH_MULTIPLE;

        // 如果目标ActivityRecord的TaskRecor为null,且clearTopAndResetStandardLaunchMode为true
        // 则设置目标ActivityRecord的TaskRecord.
        if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
            mStartActivity.setTask(reusedActivity.getTaskRecord());
        }

        if (reusedActivity.getTaskRecord().intent == null) {
            // This task was started because of movement of the activity based on affinity...
            // Now that we are actually launching it, we can assign the base intent.
            reusedActivity.getTaskRecord().setIntent(mStartActivity);
        } else {
            final boolean taskOnHome =
                    (mStartActivity.intent.getFlags() & FLAG_ACTIVITY_TASK_ON_HOME) != 0;
            //判断是否存在FLAG_ACTIVITY_TASK_ON_HOME标签,如果存在且有FLAG_ACTIVITY_NEW_TASK标签,
            //启动这个Activity后会将Launcher所在的ActivityStack拉到当前所启动的Activity所在ActivityStack后面。
            //举例,应用A启动应用B中的某个Activity,且设置的launchFlag包含FLAG_ACTIVITY_TASK_ON_HOME和FLAG_ACTIVITY_NEW_TASK;
            //当应用B退出的时候并不会回到应用A,而是回到Launcher应用。
            if (taskOnHome) {
                reusedActivity.getTaskRecord().intent.addFlags(FLAG_ACTIVITY_TASK_ON_HOME);
            } else {
                reusedActivity.getTaskRecord().intent.removeFlags(FLAG_ACTIVITY_TASK_ON_HOME);
            }
        }

        // This code path leads to delivering a new intent, we want to make sure we schedule it
        // as the first operation, in case the activity will be resumed as a result of later
        // operations.
        // 三种clear top的情况:1,launchFlag包含FLAG_ACTIVITY_CLEAR_TOP;2,launchFlag包含FLAG_ACTIVITY_NEW_DOCUMENT
        // 且不包含FLAG_ACTIVITY_MULTIPLE_TASK;3,launchMode为singleInstance或者singleTask
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
            final TaskRecord task = reusedActivity.getTaskRecord();

            // In this situation we want to remove all activities from the task up to the one
            // being started. In most cases this means we are resetting the task to its initial
            // state.
            // 将要启动的Activity所对应的ActivityRecord以上的对象从task中的ActivityRecord列表中移除
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            // The above code can remove {@code reusedActivity} from the task, leading to the
            // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
            // task reference is needed in the call below to
            // {@link setTargetStackAndMoveToFrontIfNeeded}.
            if (reusedActivity.getTaskRecord() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {
                if (top.frontOfTask) {
                    // Activity aliases may mean we use different intents for the top activity,
                    // so make sure the task now has the identity of the new intent.
                    top.getTaskRecord().setIntent(mStartActivity);
                }
                //如果栈顶的Activity就是需要启动的Activity,则调用Activity的onNewIntent()方法
                deliverNewIntent(top);
            }
        }

        mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded
                (false /* forceSend */, reusedActivity);
        //setTargetStackAndMoveToFrontIfNeeded()和resumeTargetStackIfNeeded()方法的调用会将Activity栈中的
        //reusedActivity拉起并显示到前台,当然这个过程也会涉及到将前台应用调到后台。
        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do anything
            // if that is the case, so this is it!  And for paranoia, make sure we have
            // correctly resumed the top activity.
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }

        if (reusedActivity != null) {
            setTaskFromIntentActivity(reusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                if (outActivity != null && outActivity.length > 0) {
                    // The reusedActivity could be finishing, for example of starting an
                    // activity with FLAG_ACTIVITY_CLEAR_TOP flag. In that case, return the
                    // top running activity in the task instead.
                    outActivity[0] = reusedActivity.finishing
                            ? reusedActivity.getTaskRecord().getTopActivity() : reusedActivity;
                }
                //这种情况是Activity已经被启动过,ActivityRecord实例存在于TaskRecord中,
                //一种场景就是我们启动一个应用的MainActivity后,按home键回到launcher后再进入这个应用,走的就是这个流程
                return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
            }
        }
    }
    //.....省略部分代码.......
    
}

?注释中已经做了部分说明,这里有个比较重要的方法getReusableIntentActivity(),这个方法是判断要启动的ActivityRecord是否加入到现有的TaskRecord中,这个判断会涉及到launchMode、taskAffinity和launchFlag的设定,这里我们就不展开了,以后的文章我们再来详细了解,这里我们先举个例子说明:

<activity android:name="com.example.ltst.MainActivity"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="com.example.ltst.activity.ActivitySingleTaskCustomAffinity"
    android:taskAffinity=".singleTaskAffinity"
    android:launchMode="singleTask"/>
<activity android:name="com.example.ltst.activity.ActivitySingleTask"
    android:launchMode="singleTask">
</activity>
<activity android:name="com.example.ltst.activity.ActivitySingleInstance"
    android:launchMode="singleInstance"/>
<activity android:name="com.example.ltst.activity.ActivityStandard"/>

?如上所示,我们定义了五个Activity,现在从MainActivity中分别启动另外四个Activity:

  • MainActivity > ActivitySingleTaskCustomAffinity, MainActivity的taskAffinity为默认的包名,ActivitySingleTaskCustomeAffinity自定义了taskAffinity,所以这种情况getReusableIntentActivity()返回为null.
  • MainActivity > ActivitySingleTask,MainActivity和ActivitySingleTask的launchMode和taskAffinity(不显示定义的话默认为应用包名)都是一样的,这个时候getReusableIntentActivity()返回的就是MainActivity的ActivityRecord对象;
  • MainActivity > ActivitySingleInstance,launchMode为singleInstance比较特殊,该模式下TaskRecord下只能有一个ActivityRecord,由于ActivitySingleInstance对应的TaskRecord还没有被创建过,所以此时getReusableIntentActivity()返回的也是null。
  • MainActivity > ActivityStandard, 这种情况getReusableIntentActivity返回的是nul,这是因为getReusableIntentActivity()里面有判断要启动Activity的launchMode和launchFlag,如果launchFlag没有设置FLAG_ACTIVITY_NEW_TASK且launchMode不为singleInstance和singleTask,则会返回null,但这也不是意味着ActivityStandard会被放入其他的TaskRecord中,它还是会被加入到MainActivity所在的TaskRecord中。

对于已经被启动过的Activity,且它对应的ActivityRecord还在ActivityStack中的时候,再次启动该Activity的流程(也就是App热启动的情况)大概是这样的:
在这里插入图片描述

?在ActivityStack.resumeTopActivityInnerLocke()方法中会触发一个ResumeActivityItem请求的事务,最后事务处理会执行ResumeActivityItem.excute()方法中的任务。ResumeActivityItem.excute()方法会调用ActivityThread.handleResuemActivity().

?如上面的例子中所述,对于创建新的TaskRecord有多种情况,我们来看另一种情况——App冷启动,这种情况会涉及到ActivityStack和TaskRecord的创建。

//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity, boolean restrictedBgActivity) {
    //重置变量并重新给mStartActivity,mIntent,mSourceRecord等变量赋值
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor, restrictedBgActivity);

    //.......省略部分代码....
    
    
    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getActivityStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // If the activity being launched is the same as the one currently at the top, then
    // we need to check if it should only be launched once.
    final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
    final ActivityRecord topFocused = topStack.getTopActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.mActivityComponent.equals(mStartActivity.mActivityComponent)
            && top.mUserId == mStartActivity.mUserId
            && top.attachedToProcess()
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
            // This allows home activity to automatically launch on secondary display when
            // display added, if home was the top activity on default display, instead of
            // sending new intent to the home activity on default display.
            && (!top.isActivityTypeHome() || top.getDisplayId() == mPreferredDisplayId);
    if (dontStart) {
        // For paranoia, make sure we have correctly resumed the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mRootActivityContainer.resumeFocusedStacksTopActivities();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do
            // anything if that is the case, so this is it!
            return START_RETURN_INTENT_TO_CALLER;
        }

        deliverNewIntent(top);

        // Don't use mStartActivity.task to show the toast. We're not starting a new activity
        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
        mSupervisor.handleNonResizableTaskIfNeeded(top.getTaskRecord(), preferredWindowingMode,
                mPreferredDisplayId, topStack);

        return START_DELIVERED_TO_TOP;
    }

    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTaskRecord() : null;

    // Should this be considered a new task?
    int result = START_SUCCESS;
    // 下面的几个判断是计算要启动的ActivityRecord所存放的ActivityStack,mTargetStack会被正确的赋值。
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {//冷启动会进入该条件
        newTask = true;
        //setTaskFromReuseorCreateNewTask()会创建ActivityStack
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        result = setTaskToCurrentTopOrCreateNewTask();
    }
    if (result != START_SUCCESS) {
        return result;
    }

    mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId);
    mService.getPackageManagerInternalLocked().grantEphemeralAccess(
            mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid),
            UserHandle.getAppId(mCallingUid));
    if (newTask) {
        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
                mStartActivity.getTaskRecord().taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTaskRecord());
    mTargetStack.mLastPausedActivity = null;

    mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
            false /* forceSend */, mStartActivity);

    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTaskRecord().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
            mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
        } else {
            if (mTargetStack.isFocusable()
                    && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            
            mRootActivityContainer.resumeFocusedStacksTopActivities(
                    mTargetStack, mStartActivity, mOptions);
        }
    } else if (mStartActivity != null) {
        mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
    }
    mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
            preferredWindowingMode, mPreferredDisplayId, mTargetStack);

    return START_SUCCESS;
}

?冷启动的情况下,setTaskFromReuseOrCreateNewTask会创建要启动的Activity对应的ActivityRecord所在的Activitystack和TaskRecord。然后经过mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);实现启动Activity的逻辑;RootActivityContainer.resumeFocusedStacksTopActivities()方法最终会调用ActivityStack.resumeTopActivityInnerLocked(), 启动Activity的主要逻辑就在该方法中。这个方法比较长,我们只截取部分说明

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    if (!mService.isBooting() && !mService.isBooted()) {
        // Not ready yet!
        return false;
    }
	if (DEBUG_STATES) Slog.v(TAG_STATES,
        "resumeTopActivityInnerLocked: ", new RuntimeException("resumeTopActivityInnerLocked").fillInStackTrace());

    // next即要启动的Activity
    ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

    final boolean hasRunningActivity = next != null;

    // TODO: Maybe this entire condition can get removed?
    if (hasRunningActivity && !isAttached()) {
        return false;
    }

    mRootActivityContainer.cancelInitializingActivities();


    boolean userLeaving = mStackSupervisor.mUserLeaving;
    mStackSupervisor.mUserLeaving = false;

    if (!hasRunningActivity) {
        // There are no activities left in the stack, let's look somewhere else.
        return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
    }

    next.delayedResume = false;
    final ActivityDisplay display = getDisplay();

    // If the top activity is the resumed one, nothing to do.
    if (mResumedActivity == next && next.isState(RESUMED)
            && display.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed " + next);
        return false;
    }

    if (!next.canResumeByCompat()) {
        return false;
    }

    if (shouldSleepOrShutDownActivities()
            && mLastPausedActivity == next
            && mRootActivityContainer.allPausedActivitiesComplete()) {

        boolean nothingToResume = true;
        if (!mService.mShuttingDown) {
            final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
                    && next.canShowWhenLocked();
            final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
                    && next.mAppWindowToken != null
                    && next.mAppWindowToken.containsDismissKeyguardWindow();

            if (canShowWhenLocked || mayDismissKeyguard) {
                ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
                        !PRESERVE_WINDOWS);
                nothingToResume = shouldSleepActivities();
            }
        }
        if (nothingToResume) {
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Going to sleep and all paused");
            return false;
        }
    }
    if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
        Slog.w(TAG, "Skipping resume of top activity " + next
                + ": user " + next.mUserId + " is stopped");
        return false;
    }
    mStackSupervisor.mStoppingActivities.remove(next);
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    next.sleeping = false;

    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

    // If we are currently pausing an activity, then don't do anything until that is done.
    if (!mRootActivityContainer.allPausedActivitiesComplete()) {
        if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                "resumeTopActivityLocked: Skip resume: some activity pausing.");

        return false;
    }

    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

    boolean lastResumedCanPip = false;
    ActivityRecord lastResumed = null;
    final ActivityStack lastFocusedStack = display.getLastFocusedStack();
    if (lastFocusedStack != null && lastFocusedStack != this) {

        lastResumed = lastFocusedStack.mResumedActivity;
        if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {

            if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
                    + " next=" + next + " lastResumed=" + lastResumed);
            userLeaving = false;
        }
        lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                "resumeTopActivity", userLeaving /* beforeStopping */);
    }

    // 如果Intent设置了FLAG_RESUME_WHILE_PAUSING 且上个Activity不以分屏的方式显示,则resumeWhilePasuing为true
    final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
            && !lastResumedCanPip;
    // 在启动Activity前先要让栈中的Activity进入pause状态,如果有Activity进入pause状态则pausing为true
    boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
	//如果有Activity进入了pause状态且resumeWhilePasuing为false,这个时候就会return。
    if (pausing && !resumeWhilePausing) {
        if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                "resumeTopActivityLocked: Skip resume: need to start pausing");
        if (next.attachedToProcess()) {
            next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* activityChange */, false /* updateOomAdj */);
        }
        if (lastResumed != null) {
            lastResumed.setWillCloseOrEnterPip(true);
        }
        return true;
    } else if (mResumedActivity == next && next.isState(RESUMED)
            && display.allResumedActivitiesComplete()) {
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
        return true;
    }

    //.....省略部分代码......
}

?上面截取的是让activity 栈中的Activity先进入pause状态的逻辑。这也是为什么应用A启动应用B的时候,应用A的Activity的onPause()方法会在应用B的Activity的onCreate()方法之前调用(这里没有考虑分屏的情况)。getDisplay().pauseBackStacks(userLeaving, next, false);会让前台App的Activity进入pause状态,该方法会调用到ActivityStack.startPausingLocked()方法,在这个方法中主要的逻辑是发送一个PauseActivityItem的事务。

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
        ActivityRecord resuming, boolean pauseImmediately) {
    if (mPausingActivity != null) {
        Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                + " state=" + mPausingActivity.getState());
        if (!shouldSleepActivities()) {
            completePauseLocked(false, resuming);
        }
    }
    ActivityRecord prev = mResumedActivity;

    if (prev == null) {
        if (resuming == null) {
            Slog.wtf(TAG, "Trying to pause when nothing is resumed");
            mRootActivityContainer.resumeFocusedStacksTopActivities();
        }
        return false;
    }

    if (prev == resuming) {
        Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
        return false;
    }

    if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
    else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
    mPausingActivity = prev;
    mLastPausedActivity = prev;
    mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
            || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
    prev.setState(PAUSING, "startPausingLocked");
    prev.getTaskRecord().touchActiveTime();
    clearLaunchTime(prev);

    mService.updateCpuStats();

    if (prev.attachedToProcess()) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
        try {
            EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                    prev.shortComponentName, "userLeaving=" + userLeaving);

            mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                    prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately));
        } catch (Exception e) {
            Slog.w(TAG, "Exception thrown during pause", e);
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
    } else {
        mPausingActivity = null;
        mLastPausedActivity = null;
        mLastNoHistoryActivity = null;
    }

    if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
        mStackSupervisor.acquireLaunchWakelock();
    }

    if (mPausingActivity != null) {
        if (!uiSleeping) {
            prev.pauseKeyDispatchingLocked();
        } else if (DEBUG_PAUSE) {
             Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
        }

        if (pauseImmediately) {
            completePauseLocked(false, resuming);
            return false;

        } else {
            schedulePauseTimeout(prev);
            return true;
        }

    } else {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
        if (resuming == null) {
            mRootActivityContainer.resumeFocusedStacksTopActivities();
        }
        return false;
    }
}

或许你有个疑问,既然这个地方直接return ture了,那ActivityStarter.startActivityUnchecked()调用是否就已经结束了呢;答案是肯定的。那你肯定又有疑问了,既然方法调用都结束了,那Activity到底是怎么启动的呢,因为目前只讲到了pause 之前应用的Activity,还没讲到启动Activity。要回答这个问题,这就看下pause Activity是怎么实现的了。先放张时序图,感兴趣的同学去跟一跟代码。

在这里插入图片描述

?上面的时序图主要分为两个步骤:

  • 将前台应用A退入后台,实现的过程是在PauseActivityItem.excute()方法中调用ActivityThread.handlePauseActivity()方法;

  • 当应用A退入到后台后,将应用B显示到前台,实现过程是PauseActivityItem.postExcute()中调用ActivityTaskManagerService.activityPaused(),然后经过一系列方法调用,最后执行到了ActivityStack.resumeTopActivityInnerLocked()方法,这个方法我们前面讲过,只不过前面是在if (pausing && !resumeWhilePausing)条件下return 了;而这个时候下会调用ActivitySupervisor.startSpecificActivityLocked()。startSpecificActivityLocked()会调用realStartActivityLocked()方法。

我们先看下startSpecificActivityLocked()方法

//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
	//如果Activity所属的进程已经创建,则启动Activity
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
        knownToBeDead = true;
    }
    if (getKeyguardController().isKeyguardLocked()) {
        r.notifyUnknownVisibilityLaunched();
    }

    try {
        if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                    + r.processName);
        }
		//如果进程没有创建,则创建进程,PooledLambda.obtainMessage返回一个会调用
        //ActivityManagerInternal.startProcess(mService.mAmInternal, r.processName, r.info.applicationInfo, 
        //knownToBeDead, "activity", r.intent.getComponent())的Callback,
        final Message msg = PooledLambda.obtainMessage(
                ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
        mService.mH.sendMessage(msg);
    } finally {
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
}

?App冷启动的过程会执行创建进程的过程,限于篇幅的原因,这里就不展开了,下次我们单独讲解。上面的时序图也省略了进程创建的过程,同样我们下次再补上。虽然这里省略了进程创建的过程,但是进程创建过后,也同样会调用realStartActivtiyLocked()方法来继续执行启动Activity。我们看下realStartActivityLocked()个方法:

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
      boolean andResume, boolean checkConfig) throws RemoteException {

     //.....省略部分代码......


          // Create activity launch transaction.
          final ClientTransaction clientTransaction = ClientTransaction.obtain(
                  proc.getThread(), r.appToken);

          final DisplayContent dc = r.getDisplay().mDisplayContent;
          clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                  System.identityHashCode(r), r.info,
                  // TODO: Have this take the merged configuration instead of separate global
                  // and override configs.
                  mergedConfiguration.getGlobalConfiguration(),
                  mergedConfiguration.getOverrideConfiguration(), r.compat,
                  r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                  r.icicle, r.persistentState, results, newIntents,
                  dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                          r.assistToken));

          // Set desired final state.
          final ActivityLifecycleItem lifecycleItem;
          if (andResume) {
              lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
          } else {
              lifecycleItem = PauseActivityItem.obtain();
          }
          clientTransaction.setLifecycleStateRequest(lifecycleItem);

          // Schedule transaction.
          mService.getLifecycleManager().scheduleTransaction(clientTransaction);

  //.....省略部分代码......

  return true;
}

这个方法的核心是启动一个设置了LaunchActivityItem回调和ResumeActivityItem请求的事务。有了前面的经验我们知道,最终LauncherActivityItem和ResumeActivityItem的execute()方法会被执行,我们看下他们的execute()方法实现:

//LaunchActivityItem.java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
      PendingTransactionActions pendingActions) {
  Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
  ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
          mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
          mPendingResults, mPendingNewIntents, mIsForward,
          mProfilerInfo, client, mAssistToken);
  client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
  Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

//ResumeActivityItem.java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
      PendingTransactionActions pendingActions) {
  Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
  client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
          "RESUME_ACTIVITY");
  Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

?方法很简单,分别调用了ActivityThread.handleLauncheActivity()、ActivityThread.handleResumeActivity();这两个方法最终会调用到Activity的onCreate()、onResume()方法。这个时候你可能就有疑问了,那onStart()方法呢,不是应该在onResume之前调用的吗。这个就要从TransactionExecutor.execute()说起,我们看下这个方法

//TransactionExecutor.java

public void execute(ClientTransaction transaction) {
  if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");

  //.....省略部分代码....
  //先执行callback,也就是会先执行LaunchActivityItem.execute()方法
  executeCallbacks(transaction);
  //然后调用executeLifecyleState()方法,这个方法会处理事务中的请求事件。
  executeLifecycleState(transaction);
  mPendingActions.clear();
  if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
  final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
  if (lifecycleItem == null) {
      // No lifecycle request, return early.
      return;
  }

  final IBinder token = transaction.getActivityToken();
  final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
  if (DEBUG_RESOLVER) {
      Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
              + lifecycleItem + " for activity: "
              + getShortActivityName(token, mTransactionHandler));
  }

  if (r == null) {
      // Ignore requests for non-existent client records for now.
      return;
  }

  //在调用ActivityLifeCycleItem(ResumeActivityItem的父类)的execute()方法之前,先调用cycleToPath()方法;
  //lifecycleItem.getTargetState()即为ResumeActivityItem.getTargetState()返回的值3(ON_RESUME).
  cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

  // Execute the final transition with proper parameters.
  lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
  lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

@VisibleForTesting
public void cycleToPath(ActivityClientRecord r, int finish, ClientTransaction transaction) {
  cycleToPath(r, finish, false /* excludeLastState */, transaction);
}

private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
      ClientTransaction transaction) {
  //经过execute()中执行executeCallbacks(transaction)后,Activity就处于ON_CTREATE状态,这个时候start值为1(ON_CREATE)。
  final int start = r.getLifecycleState();
  if (DEBUG_RESOLVER) {
      Slog.d(TAG, tId(transaction) + "Cycle activity: "
              + getShortActivityName(r.token, mTransactionHandler)
              + " from: " + getStateName(start) + " to: " + getStateName(finish)
              + " excludeLastState: " + excludeLastState);
  }
  //这个时候start = 1,finish = 3, excludeLastState = true;mHelper.getLifecyclePath方法会返回只有一个元素(值为2)的整型数组对象
  final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
  performLifecycleSequence(r, path, transaction);
}

private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
      ClientTransaction transaction) {
  final int size = path.size();
  for (int i = 0, state; i < size; i++) {
      state = path.get(i);
      if (DEBUG_RESOLVER) {
          Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                  + getShortActivityName(r.token, mTransactionHandler)
                  + " to state: " + getStateName(state));
      }
      //这个时候state就是`mHelper.getLifecyclePath(start, finish, excludeLastState);`返回的数组中的元素值2(ON_START)
      //所以这时候会调用ActivityThread.handleStartActivity()方法,最终Activity.onStart()方法会被调用。
      switch (state) {
          //ON_CREATE、ON_START、ON_RESUEM、ON_PAUSE、ON_STOP、ON_DESTROY、ON_RESTART
          //定义在ActivityLifecycleItem.java中,他们的值分别为:0、1、2、3、4、5、6、7
          case ON_CREATE:
              mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                      null /* customIntent */);
              break;
          case ON_START:
              mTransactionHandler.handleStartActivity(r, mPendingActions);
              break;
          case ON_RESUME:
              mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                      r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
              break;
          case ON_PAUSE:
              mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                      false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                      "LIFECYCLER_PAUSE_ACTIVITY");
              break;
          case ON_STOP:
              mTransactionHandler.handleStopActivity(r.token, false /* show */,
                      0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                      "LIFECYCLER_STOP_ACTIVITY");
              break;
          case ON_DESTROY:
              mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                      0 /* configChanges */, false /* getNonConfigInstance */,
                      "performLifecycleSequence. cycling to:" + path.get(size - 1));
              break;
          case ON_RESTART:
              mTransactionHandler.performRestartActivity(r.token, false /* start */);
              break;
          default:
              throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
      }
  }
}

?代码中注释已经做了说明了,总结下就是在调用ResumeActivityItem.execute()方法之前,会先执行cycleToPath()判断Activity的起始状态和目标状态,如果后者大于前者,则需要执行两者之间的状态。至此冷启动情况下启动Activity就分析完了, 至于Activity启动后显示的过程可以参照下之前的文章《Activity UI显示流程分析》。当然还有很多细节没有展开,比如ActivityStack、TaskRecord的创建和更新,以及进程创建的过程;这写以后有机会再分享,大家也可以自己研究,文中的时序图可作为参考。

结束

?最后我们稍稍总结下,Activity启动过程主要分为两个过程:一是找到这个Activity(得到ActivityRecord对象);二是启动它,而启动过程又分为两种情况:一种在Activity栈中有Activity对应的ActivityRecord对象(这个会跟launchMode和launch flag有关),这种情况会走Activity的onNewIntent()方法;另一种是Activity栈中没有Activity对应的ActivityRecord,这种情况下又可分为多种子情况,但是我们不比纠结每种情况的细节;文中我们是分析了冷启动一个App的情况,虽然进程创建过程没有展开,但是后面Activity的启动流程还是一致的。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 21:47:27  更:2021-08-07 21:47:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:55:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码