Activity启动流程总结-生命周期

前言

对于Activity的启动流程,从事Android开发的同学都很熟悉。这里仅结合自己的理解,通过博文梳理和记录Activity启动流程关键节点,便于记忆和将来回顾。

官方Activity生命周期示意图:

activity-lifecycle

当 Activity A 启动 Activity B 时,它们各自的生命周期回调顺序是:

  1. Activity A 的 onPause() 方法执行。
  2. Activity B 的 onCreate()、onStart() 和 onResume() 方法依次执行。(Activity B 现在具有用户焦点。)
  3. 然后,如果 Activity A 在屏幕上不再可见,则其 onStop() 方法执行。

大家对于这样的结论都已熟知,但是ActivityManagerService是如何调度各Activity的生命回调,以及在什么时机调度等问题,就需要进入Activity的启动流程来找答案。

源码探究

文中源码基于Android 9.0

startActivity

首先通过activity.startActivity发起启动Activity的请求指令,startActivity最终调用Instrumentation的execStartActivity方法:

[Instrumentation.java]

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
   
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
   
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    // 省略ActivityMonitor相关部分
    // ···
    try {
   
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        // 获取IActivityManager binder通信接口,执行startActivity方法调用到AMS端
        int result = ActivityManager.getService()
            .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;
}

该方法中通过IActivityManager.startActivity方法将指令和参数传递给ActivityManagerService,触发ActivityManagerService对应的startActivity方法。

startActivityAsUser

ActivityManagerService的startActivity方法中又执行到startActivityAsUser方法:

[ActivityManagerService.java]

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,
        boolean validateIncomingUser) {
   
    enforceNotIsolatedCaller("startActivity");

    // 根据uid检查权限并返回修正后的uid
    userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // TODO: Switch to user app stacks here.
    // 获取ActivityStarter(用于配置和执行启动Activity),调用其execute方法执行启动
    return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();
}

该方法中通过ActivityStarter保存启动参数,然后执行启动,execute方法中将调用startActivityMayWait方法。

startActivityMayWait

[ActivityStarter.java]

private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
        int userId, TaskRecord inTask, String reason,
        boolean allowPendingRemoteAnimationRegistryLookup) {
   
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
   
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
    // 标记intent有明确设置接收的组件
    boolean componentSpecified = intent.getComponent() != null;

    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;
    }
    
    // 创建intent的副本
    // 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);
    // 省略拦截处理跳转InstantAPP安装相关部分 ···
    
    // 通过PackageManagerService查询该intent是否有匹配的ResolveInfo
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, mRequest.filterCallingUid));
    if (rInfo == null) {
   
        // 省略ResolveInfo未找到情况的处理部分
        // ···
    }
    // Collect information about the target of the Intent.
    // 获取ResolveInfo中的ActivityInfo
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    
    synchronized (mService) {
   
        // 获取处于焦点的ActivityStack
        final ActivityStack stack = mSupervisor.mFocusedStack;
        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();
        
        // 省略heavy-weight进程处理部分 ···
        
        // 用来保存start Activity过程中创建或复用的ActivityRecord
        final ActivityRecord[] outRecord = new ActivityRecord[1];
        // 进一步执行启动Activity
        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);

        Binder.restoreCallingIdentity(origId);
        
        // 省略更新Configuration部分 ···
        
        // 省略对启动结果outResult的处理部分,若存在需要等待目标Activity所在进程启动
        // 或等待特定Activity可见等情况,则将阻塞等待唤醒再返回结果。
        // ···
    }
}

该方法中对intent做了检查之后,调用startActivity方法进一步进行启动流程,其中又调用另一个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) {
   
    // err记录运行结果,默认记为START_SUCCESS
    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;
    
    // 调用端(即发起start请求的APP进程)对应的ProcessRecord
    ProcessRecord callerApp = null;
    if (caller != null) {
   
        // 从AMS中的缓存集合获取
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
   
            // 获取调用端pid、uid
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
   
            // 正常情况下,APP进程都会在AMS有一个ProcessRecord。若无,则认为非法。
            Slog.w(TAG, "Unable to find app for caller " + caller
                    + " (pid=" + callingPid + ") when starting: "
                    + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    
    // ActivityRecord对应表示Activity栈中的一个Activity
    // sourceRecord表示调用端Activity
    ActivityRecord sourceRecord = null;
    // resultRecord表示在onActivityResult接收结果的Activity
    ActivityRecord resultRecord = null;
    // resultTo表示调用端Activity的token,可通过它获取Activity对应的ActivityRecord
    if (resultTo != null) {
   
        sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                "Will send result to " + resultTo + " " + sourceRecord);
        if (sourceRecord != null) {
   
            if (requestCode >= 0 && !sourceRecord.finishing) {
   
                // 当需要回调onActivityResult的情况下,即调用startActivityForResult方法
                // requestCode参数大于0,resultRecord即为sourceRecord
                resultRecord = sourceRecord;
            }
        }
    }
    
    // 获取intent中设置的启动标识
    final int launchFlags = intent.getFlags();

    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
   
        // 省略处理FLAG_ACTIVITY_FORWARD_RESULT相关部分
        // ···
    }
    
    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
   
        // We couldn't find a class that can handle the given Intent.
        // That's the end of that!
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
   
        // We couldn't find the specific class specified in the Intent.
        // Also the end of the line.
        err = ActivityManager.START_CLASS_NOT_FOUND;
    }
    
    // 省略检查语音会话时启动Activity部分,若目标Activity不支持VOICE类别,则标记
    // err = ActivityManager.START_NOT_VOICE_COMPATIBLE
    // ···
    
    final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();

    // 若err标记为失败,则终止启动
    if (err != START_SUCCESS) {
   
        if (resultRecord != null) {
   
            // 通知调用端onActivityResult,并传回RESULT_CANCELED
            resultStack.sendActivityResultLocked(
                    -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
        }
        SafeActivityOptions.abort(options);
        return err;
    }
    
    // 检查权限,若权限不通过则将abort标记为true
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
            requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
            inTask != null, callerApp, resultRecord, resultStack);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);
            
    // 省略动画选项设置相关部分 ···
    
    // 省略IActivityController部分,用于监听拦截Activity启动,可通过AMS.setActivityController
    // 设置监听器,若拦截将标记abort=true。
    // 省略ActivityStartInterceptor部分 ···
    
    // 判断是否终止
    if (abort) {
   
        if (resultRecord != null) {
   
            // 通知调用端onActivityResult,并传回RESULT_CANCELED
            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                    RESULT_CANCELED, null);
        }
        // We pretend to the caller that it was really started, but
        // they will just get a cancel result.
        ActivityOptions.abort(checkedOptions);
        return START_ABORTED;
    }
    
    // 省略权限检查部分 ···
    // 省略临时安装APP部分 ···
    
    // 新建ActivityRecord,保存Activity启动相关参数
    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;
    }
    
    // 省略赋值AppTimeTracker部分 ···
    // 省略检查是否允许应用切换部分 ···
    
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity);
}

该方法中对当前能否启动目标Activity进行了各项检查,并创建ActivityRecord用以保存Activity启动信息,其中还有涉及Activity启动拦截器的调用(若有设置)。最后调用了另一个重载方法startActivity,其中又调用startActivityUnchecked方法。

startActivityUnchecked

[ActivityStarter.java]

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
   

    // 初始化ActivityStarter的成员变量,用当前启动信息设置
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);

    // 调整启动标识
    computeLaunchingTaskFlags();

    // 获取sourceRecord的ActivityStack,若调用端Activity即将finish,则修改启动标识
    computeSourceStack();
    
    // 设置调整后的启动标识
    mIntent.setFlags(mLaunchFlags);
    
    // 根据启动标识和启动模式检查是否新建TASK或加入现有TASK。若加入现有TASK,则返回该TASK中可重用的ActivityRecord。
    ActivityRecord reusedActivity = getReusableIntentActivity();
    
    // 省略窗口模式相关部分 ···
    
    if (reusedActivity != null) {
   
        // 省略设置ActivityRecord和对应TaskRecord,根据启动模式和启动标识清理任务栈,
        // 触发复用Activity的onNewIntent方法等等部分
        // ···
    }
    
    // 省略检查packageName部分 ···
    // 省略当目标Activity与当前顶部Activity一致时,根据启动标识和模式判断是否不启动新Activity以及对应的处理的相关部分
    
    // 省略设置TaskRecord部分
    
    // 省略权限设置
    // ···
    
    // 进行TaskRecord、APP Window Token、动画、窗口复用等相关检查和配置
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    if (mDoResume) {
   
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
   
            // If the activity is not focusable, we can't resume it, but still would like to
            // make sure it becomes visible as it starts (this will also trigger entry
            // animation). An example of this are PIP activities.
            // Also, we don't want to resume activities in a task that currently has an overlay
            // as the starting activity just needs to be in the visible paused state until the
            // over is removed.
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            // Go ahead and tell window manager to execute app transition for this activity
            // since the app transition will not be triggered through the resume channel.
            mService.mWindowManager.executeAppTransition();
        } else {
   
            // If the target stack was not previously focusable (previous top running activity
            // on that stack was not visible) then any prior calls to move the stack to the
            // will not update the focused stack.  If starting the new activity now allows the
            // task stack to be focusable, then ensure that we now update the focused stack
            // accordingly.
            if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
   
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            // resumeFocusedStackTopActivityLocked方法进一步执行启动操作
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else if (mStartActivity != null) {
   
        // 加入最近任务列表
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    }
    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
            preferredLaunchDisplayId, mTargetStack);

    return START_SUCCESS;
}

该方法中会进行启动标识和启动模式检查,判断是否要复用的TaskRecord、ActivityRecord还是重新创建。若要新启动一个Activity,则调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,继续进行启动流程。

resumeFocusedStackTopActivityLocked

[ActivityStackSupervisor.java]

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
   

    if (!readyToResume()) {
   
        return false;
    }

    // 判断目标Activity栈是否处于焦点,是的话则调用其resumeTopActivityUncheckedLocked方法进一步进行启动流程
    if (targetStack != null && isFocusedStack(targetStack)) {
   
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    // ···

    return false;
}

该方法中主要对Activity栈的焦点进行检查,之后便通过ActivityStack的resumeTopActivityUncheckedLocked继续执行启动流程。

resumeTopActivityUncheckedLocked

[ActivityStack.java]

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
   
    // inResumeTopActivity标记当前处于resumeTopActivity过程中,用于避免重复递归调用。
    if (mStackSupervisor.inResumeTopActivity) {
   
        // Don't even start recursing.
        return false;
    }

    boolean result = false;
    try {
   
        // Protect against recursion.
        mStackSupervisor.inResumeTopActivity = true;
        // Activity启动流程核心方法
        result = resumeTopActivityInnerLocked(prev, options);

        // When resuming the top activity, it may be necessary to pause the top activity (for
        // example, returning to the lock screen. We suppress the normal pause logic in
        // {@link #resume
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值