第10章:Activity启动流程源码解析:从startActivity到onCreate的完整调用链

各位同学,今天我们来啃一块硬骨头——Activity的启动流程。说实话,这个流程我前前后后看了不下十遍,每次看都有新收获。你想想看,一个简单的startActivity()调用,背后竟然牵扯到InstrumentationActivityThreadAMS三大核心类,跨进程通信、Binder机制、生命周期调度全用上了。

我个人习惯把启动流程分成三个阶段来看:

  • 应用内阶段:从startActivityInstrumentation,再到AMS
  • AMS处理阶段:进程创建、ActivityRecord管理、栈调度
  • 应用内回调阶段:从ActivityThreadonCreate

咱们今天就重点剖析第一阶段和第三阶段,AMS那块我会在后续章节单独展开。

10.1 起点:startActivity()到底干了什么?

我们先从最熟悉的入口开始。你平时写startActivity(intent),其实它内部调用了startActivityForResult()。嗯,这里要注意,如果你传了requestCode,系统会帮你处理回调;如果没传,默认是-1。

// Activity.java
@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

看到没?最终都走到startActivityForResult。这里有个细节——mMainThread是什么?它就是ActivityThread的实例,每个应用进程只有一个。

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        // 核心调用
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        // ...
    }
}

这里我当年踩过一个坑:mToken是什么?它是IBinder类型,代表当前Activity在AMS中的令牌。AMS通过这个token来识别是哪个Activity发起的请求。说白了,这就是一个跨进程的身份凭证。

10.2 Instrumentation:幕后总指挥

接下来进入Instrumentation。这个类很多人不熟悉,但它其实是Activity生命周期的总调度器。我建议你把Instrumentation理解成「Android系统的导演」,它负责协调Activity的创建、启动、销毁等所有动作。

// Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // 1. 获取ApplicationThread(Binder服务端)
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // 2. 检查ActivityMonitor(用于测试)
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            for (int i = mActivityMonitors.size() - 1; i >= 0; i--) {
                // ...
            }
        }
    }
    // 3. 通过AMS代理发起跨进程调用
    int result = ActivityManager.getService().startActivity(
            whoThread, who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);
    // ...
}

关键点来了:ActivityManager.getService()返回的是IActivityManager的Binder代理对象。这个代理对象通过ServiceManager获取到AMS的Binder引用。也就是说,从这一刻起,调用就跨进程了。

核心理解Instrumentation.execStartActivity()是应用进程向系统进程发起请求的桥梁。它把ApplicationThread(应用端的Binder服务)传给AMS,让AMS后续能回调应用进程。

10.3 AMS:系统大管家

AMS收到请求后,会做一系列复杂的校验和调度。这里我只说关键路径,完整的AMS逻辑我们后面专门开一章讲。

// ActivityManagerService.java
@Override
public 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());
}

AMS会做以下几件事:

  1. 检查权限:调用方是否有启动目标Activity的权限
  2. 解析Intent:通过PackageManager找到目标Activity
  3. 检查进程:目标Activity所在的进程是否已启动
  4. 创建ActivityRecord:在AMS中记录这个Activity的信息
  5. 栈管理:决定Activity放在哪个Task中

如果目标进程还没启动,AMS会通过Process.start()创建新进程。进程创建完成后,会调用ActivityThread.main(),然后通过attach()方法把ApplicationThread注册到AMS。

避坑指南:我曾经在分析一个ANR问题时,发现AMS在等待目标进程启动时超时了。原因是目标进程的Application.onCreate()里做了太多耗时操作。记住,AMS等待进程启动是有超时时间的,默认10秒。

10.4 ActivityThread:应用进程的主心骨

当AMS准备好一切后,它会通过ApplicationThread回调应用进程。这个回调是Binder调用,发生在Binder线程池中。

// ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client) {
        // 封装成ActivityClientRecord
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        // ...
        
        // 发送消息到主线程Handler
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
}

这里有个设计精妙之处:scheduleLaunchActivity是在Binder线程中执行的,但它通过sendMessage把任务交给了主线程的Handler。为什么要这么做?因为Activity的生命周期回调必须在主线程执行,而Binder线程不是主线程。

10.5 H类:主线程的消息调度器

HActivityThread的内部类,继承自Handler。它负责处理所有来自AMS的消息。

// ActivityThread.java
private class H extends Handler {
    public static final int LAUNCH_ACTIVITY = 100;
    public static final int PAUSE_ACTIVITY = 101;
    // ... 还有很多
    
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                // 从Message中取出ActivityClientRecord
                ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                // 调用handleLaunchActivity
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            } break;
        }
    }
}

你看,LAUNCH_ACTIVITY消息被分发到handleLaunchActivity方法。这个方法会做三件大事:

  1. 通过performLaunchActivity创建Activity实例
  2. 调用Activity.onCreate()
  3. 通过handleResumeActivity触发onResume()

10.6 最终章:performLaunchActivity与onCreate

终于到了创建Activity实例的环节。这里我建议你重点关注performLaunchActivity的实现:

// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 1. 获取ActivityInfo
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    
    // 2. 通过ClassLoader创建Activity实例
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    Activity activity = r.packageInfo.getActivityFactory().newActivity(cl, aInfo.name, r.intent);
    
    // 3. 创建Application(如果还没创建)
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
    // 4. 创建ContextImpl
    ContextImpl appContext = createBaseContextForActivity(r, activity);
    
    // 5. 将Activity与ContextImpl、Application关联
    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,
            r.assistToken);
    
    // 6. 调用onCreate
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    // 7. 设置Activity的状态为已创建
    r.activity = activity;
    r.stopped = true;
    mActivities.put(r.token, r);
    
    return activity;
}

看到第2步了吗?Activity是通过ClassLoader反射创建的。这意味着你的Activity类必须有一个无参构造器。我记得有一次,我在Activity里加了一个带参数的构造器,结果运行时直接崩溃了。嗯,这个坑我帮你们踩过了。

第6步调用了Instrumentation.callActivityOnCreate(),最终会调用到Activity.performCreate(),然后才是onCreate()

// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

// Activity.java
final void performCreate(Bundle icicle) {
    restoreHasCurrentPermissionRequest(icicle);
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

至此,onCreate()终于被调用了。从startActivity()onCreate(),经历了应用进程→AMS→应用进程的跨进程通信,涉及了Binder、Handler、反射等核心技术。

总结一下调用链

startActivity()
  → startActivityForResult()
    → Instrumentation.execStartActivity()
      → AMS.startActivity()  [跨进程]
        → AMS处理(权限、进程、栈)
          → ApplicationThread.scheduleLaunchActivity()  [跨进程回调]
            → H.handleMessage(LAUNCH_ACTIVITY)
              → handleLaunchActivity()
                → performLaunchActivity()
                  → ClassLoader.newInstance()  [反射创建Activity]
                  → activity.attach()  [关联Context]
                  → Instrumentation.callActivityOnCreate()
                    → Activity.performCreate()
                      → Activity.onCreate()  [你终于等到了]

10.7 面试官常问的几个点

最后,我总结几个面试中经常被问到的问题,你们可以自己思考一下:

问题 核心答案
为什么需要Instrumentation? Instrumentation是Activity生命周期的总调度器,它让系统可以在Activity创建前后插入监控逻辑(比如测试框架的ActivityMonitor)
ApplicationThread的作用? 它是应用进程暴露给AMS的Binder接口,AMS通过它来调度应用进程的Activity生命周期
为什么用Handler而不是直接回调? 因为AMS的回调发生在Binder线程,而Activity生命周期必须在主线程执行。Handler负责线程切换
Activity实例是谁创建的? ActivityThread通过ClassLoader反射创建,不是AMS创建的。AMS只负责调度决策

注意事项:以上分析基于Android 10(API 29)的源码。不同版本的Android在细节上可能有差异,比如Android 12引入了ClientTransaction来统一管理生命周期事务。但核心思想是一致的。

好了,这一章的内容就到这里。下一章我们会深入AMS内部,看看它到底是怎么管理Activity栈的。到时候我会分享一个我在做多窗口适配时遇到的真实案例,保证精彩。