Android Activity启动流程详细分析

Android Activity启动流程详细分析

概述

Activity启动是Android系统中最核心的功能之一。本文将从Activity的startActivity方法开始,一步一步详细分析Activity是如何启动另一个Activity的完整流程。整个流程涉及应用进程和系统进程之间的协作,通过Binder IPC进行通信。

启动流程总览

Activity启动流程可以分为三个主要阶段:

  1. 应用进程准备阶段
  2. 系统进程决策与调度阶段
  3. 应用进程执行阶段

详细启动流程分析

1. 应用进程准备阶段

1.1 Activity.startActivity() 方法调用

当我们在Activity中调用startActivity(Intent intent)方法时,实际调用的是Activity类中的以下代码:

less 复制代码
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    getAutofillClientController().onStartActivity(intent, mIntent);
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}
1.2 Activity.startActivityForResult() 方法

startActivityForResult方法进一步处理启动请求:

less 复制代码
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                   @Nullable Bundle options) {
    Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
}

这里将启动任务委托给了Instrumentation类。

1.3 Instrumentation.execStartActivity() 方法

Instrumentation是应用进程与系统进程之间的桥梁,它的execStartActivity()方法负责执行实际的启动操作:

java 复制代码
@UnsupportedAppUsage
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
​
    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        //获取到 IActivityTaskManager,实际就是 ActivityTaskManagerService
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getOpPackageName(), who.getAttributionTag(), 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;
}

在这个方法中,通过ActivityTaskManager.getService()获取到系统服务的Binder代理对象,然后调用其startActivity()方法,这是一个跨进程调用。

2. 系统进程决策与调度阶段

2.1 ActivityTaskManagerService接收请求

系统进程中的ActivityTaskManagerService(ATMS)接收到来自应用进程的启动请求:

arduino 复制代码
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
                               Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                               int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}
scss 复制代码
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("startActivityAsUser");
​
    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
​
    // getActivityStartController返回的是 ActivityStarter
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();
}
2.2 ActivityStarter.execute() 方法

ActivityStarter是启动Activity的"大脑",负责所有的校验和决策逻辑:

scss 复制代码
int execute() {
    try {
        // TODO(b/64750076): Look into passing request directly to these methods to allow
        // for transactional diffs and preprocessing.
        if (mRequest.mayWait) {
            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                    mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                    mRequest.intent, mRequest.resolvedType,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                    mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                    mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                    mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup,
                    mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
        } else {
            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                    mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                    mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                    mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                    mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                    mRequest.outActivity, mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup,
                    mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
        }
    } finally {
        onExecutionComplete();
    }
}
2.3 startActivityMayWait() 方法

当需要等待Activity启动结果时(通常情况),会调用startActivityMayWait()方法:

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) {
    
    // 1. 检查Intent中的文件描述符,防止泄露
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    
    // 2. 解析Intent获取目标Activity信息
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */, computeResolveFilterUid(
                    callingUid, requestRealCallingUid, mRequest.filterCallingUid));
    
    // 3. 获取ActivityInfo
    ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
    if (aInfo != null) {
        aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
    }
    
    // 4. 处理特殊情况(如重量级应用、托管应用等)
    // ...
    
    // 5. 调用startActivity()方法继续执行
    return startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
            voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
            ignoreTargetSecurity, componentSpecified, outActivity, inTask, reason,
            allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
            allowBackgroundActivityStart);
}
2.4 startActivity() 方法

startActivity()方法是核心的启动方法:

arduino 复制代码
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) {
    
    // 1. 权限检查
    // 2. Intent解析
    // 3. 创建ActivityRecord对象
    // 4. 调用startActivityUnchecked()方法
    return startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
}
2.5 startActivityUnchecked() 方法

这是Activity启动流程中最核心的方法,负责具体的启动逻辑:

scss 复制代码
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity, boolean restrictedBgActivity) {
    
    // 1. 初始化状态
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord,
            voiceSession, voiceInteractor, restrictedBgActivity);
    
    // 2. 计算启动标志
    computeLaunchingTaskFlags();
    
    // 3. 计算源任务栈
    computeSourceStack();
    
    // 4. 查找可复用的Activity
    ActivityRecord reusedActivity = getReusableIntentActivity();
    
    // 5. 处理复用情况
    if (reusedActivity != null) {
        // 如果找到可复用的Activity
        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
        setTaskFromIntentActivity(reusedActivity);
        // ...
    } else {
        // 6. 处理不复用情况
        // 根据不同情况调用不同的任务创建方法
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            // 创建新任务
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
        } else if (mSourceRecord != null) {
            // 在源任务中启动
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            // 在指定任务中启动
            result = setTaskFromInTask();
        } else {
            // 在当前顶部任务中启动
            result = setTaskToCurrentTopOrCreateNewTask();
        }
    }
    
    // 7. 权限处理
    mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId);
    
    // 8. 启动Activity
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    
    // 9. 恢复Activity
    if (mDoResume) {
        mRootActivityContainer.resumeFocusedStacksTopActivities(
                mTargetStack, mStartActivity, mOptions);
    }
    
    return START_SUCCESS;
}
2.6 任务栈管理

在startActivityUnchecked()方法中,系统会根据launch mode和Intent flags来决定如何管理任务栈:

  1. setTaskFromReuseOrCreateNewTask() : 创建新任务或复用现有任务
  2. setTaskFromSourceRecord() : 在源Activity的任务中启动
  3. setTaskFromInTask() : 在指定任务中启动
  4. setTaskToCurrentTopOrCreateNewTask() : 在当前顶部任务中启动

3. 应用进程执行阶段

3.1 跨进程回调应用进程

系统进程通过Binder IPC回调到目标Activity所在的应用进程。这个回调的接收者是ApplicationThread。

3.2 ApplicationThread接收回调

ApplicationThread是ActivityThread的内部类,它是一个Binder对象,运行在应用进程中。它接收到scheduleTransaction()调用,其中包含了启动Activity的指令。

3.3 H(Handler)处理消息

ApplicationThread将接收到的Binder调用转换成Message,通过一个Handler(名为H)发送到应用进程的主线程消息队列中。

3.4 ActivityThread处理指令

主线程的H处理消息,调用ActivityThread的handleLaunchActivity()方法:

scss 复制代码
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    // 1. 创建Activity实例
    Activity a = performLaunchActivity(r, customIntent);
    
    // 2. 调用Activity的onResume方法
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
        }
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && pendingActions != null);
    }
    
    return a;
}
3.5 performLaunchActivity() 创建Activity
ini 复制代码
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        return null;
    }

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

    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        // 1. 通过类加载器创建Activity实例
        java.lang.ClassLoader cl = appContext.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 {
        // 2. 创建Application实例(如果尚未创建)
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity != null) {
            // 3. 创建ContextImpl
            ContextImpl appContext = createBaseContextForActivity(r);
            
            // 4. 调用Activity.attach()绑定上下文
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);

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

            // 5. 调用Activity的onCreate方法
            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            
            // ...
        }
        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;
}

4. 后续生命周期调用

在handleLaunchActivity()之后,系统进程会继续通过同样的IPC -> Handler机制,依次调度start、resume等方法。

关键概念详解

Launch Mode

Android支持四种启动模式:

  1. standard:默认模式,每次启动都会创建新实例
  2. singleTop:如果Activity已在栈顶,则复用并调用onNewIntent()
  3. singleTask:在整个系统中只有一个实例,会清除其上的所有Activity
  4. singleInstance:独占一个任务栈,只有一个实例

Intent Flags

常用的Intent Flags:

  • FLAG_ACTIVITY_NEW_TASK:在新任务中启动Activity
  • FLAG_ACTIVITY_CLEAR_TOP:清除目标Activity之上的所有Activity
  • FLAG_ACTIVITY_SINGLE_TOP:如果Activity已在栈顶则复用
  • FLAG_ACTIVITY_NO_HISTORY:Activity不会保留在历史栈中

启动流程时序图

scss 复制代码
客户端ActivityInstrumentationActivityTaskManagerServiceActivityStarterActivityStack目标应用进程ActivityThreadActivitystartActivity()startActivity() [IPC]obtainStarter().execute()startActivityMayWait()startActivity()startActivityUnchecked()setInitialState()computeLaunchingTaskFlags()computeSourceStack()getReusableIntentActivity()setTargetStackAndMoveToFrontIfNeeded()setTaskFromIntentActivity()setTaskFromReuseOrCreateNewTask()/setTaskFromSourceRecord()alt[ 找到可复用Activity ][ 未找到可复用Activity ]startActivityLocked()scheduleLaunchActivity() [IPC]H.handleMessage()handleLaunchActivity()performLaunchActivity()onCreate()scheduleResumeActivity() [IPC]H.handleMessage()onResume()alt[ 需要恢复 ]客户端ActivityInstrumentationActivityTaskManagerServiceActivityStarterActivityStack目标应用进程ActivityThreadActivity

总结

Activity启动流程是一个复杂而精密的过程,涉及多个组件的协作:

  1. 应用进程负责发起启动请求,并在系统调度后执行具体的生命周期方法
  2. 系统进程(ATMS/ActivityStarter)负责权限检查、Intent解析、任务栈管理等核心决策
  3. Binder IPC是应用进程和系统进程之间通信的桥梁
  4. Instrumentation作为监控钩子,贯穿整个启动流程
  5. ActivityStack负责管理Activity的回退栈

理解这个流程对于Android开发和系统优化都有重要意义,特别是在处理启动性能、任务管理、生命周期等问题时。

相关推荐
littleplayer2 小时前
SwiftUI 导航
前端
用户92426257007312 小时前
Vue 组件入门学习笔记:局部注册、全局注册与 Props 传值详解
前端
云枫晖2 小时前
Webpack系列-构建性能优化实战:从开发到生产
前端·webpack·性能优化
Patrick_Wilson2 小时前
AI会如何评价一名前端工程师的技术人格
前端·typescript·ai编程
顾安r2 小时前
11.10 脚本算法 五子棋 「重要」
服务器·前端·javascript·游戏·flask
一枚前端小能手3 小时前
「周更第11期」实用JS库推荐:Pinia
前端·javascript·vue.js
kirinlau3 小时前
requst payload和query string parameters
前端·javascript
合作小小程序员小小店3 小时前
web网页开发,在线%就业信息管理%系统,基于idea,html,layui,java,springboot,mysql。
java·前端·spring boot·后端·intellij-idea
刘一说3 小时前
在 Web 地图上可视化遥感数据:以芜湖市为例
前端·遥感