源码解读|Activity 的启动流程(API 29)

1. 前言

由于系统极强的封装特性,我们在启动 Activity 时并不知道系统内部都是如何完成整个的启动流程的?如何创建一个 Activity 对象?什么时候调用 onCreate() 方法的?
本文中所有源码都是基于 Android API 29。

2. Activity 的启动方式

Activity 的启动可以通过 startActivity() 或者 startActivityForResult(),两者的区别在于是否要接收来自被启动 Activity 的返回结果。

        Intent intent = new Intent(activity, CaptureActivity.class);
        activity.startActivity(intent);  //不接收来自 CaptureActivity 的返回结果

        Intent intent = new Intent(activity, CaptureActivity.class); //接收来自 CaptureActivity 的返回结果
        activity.startActivityForResult(intent, REQUEST_CAPTURE);

3. 源码解析

3.1 启动 Activity

无论我们是通过 startActivity() 各种重载的方法还是通过 startActivityForResult() 方法启动 Activity,最后都会调用 Activity 的 startActivityForResult(Intent intent, int requestCode, Bundle options)。Context 是一个抽象类,有抽象方法 startActivity,ContextWrapper 继承自 Context ,是 Context 的代理类,实现了 startActivity;Activity 继承自 ContextWrapperTheme,ContextWrapperTheme 继承自 ContextWrapper,所以最终在 Activity 中实现的 startActivity 实际上是抽象类 Context 中的 startActivity 方法。

  • startActivityForResult()
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
               mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
       } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

1)mParent,是一个 Activity 对象,表示当前 Activity 的父 Activity,判断 mParent 是否为空,为空直接执行步骤4,不为空执行2,3;
2)mInstrumentation.execStartActivity,调用了 Instrumentation 的 execStartActivity 方法;
3)mMainThread.sendActivityResult,如果步骤2中返回结果不为空,调用ActivityThread 的 sendActivityResult 方法;
4)mParent 为空,调用父 Activity 的 startActivityFromChild 方法;

先来看看步骤2中 Instrumentation 的 execStartActivity 方法,在这里利用了 Binder 机制,跨进程调用了 ATMS(ActivityTaskManagerService)的 startActivity 方法,ATMS 运行在系统服务进程中。

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.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;
    }

1)ActivityTaskManager.getService().startActivity 即是调用了 ATMS 的 startActivity 方法;
2)checkStartActivityResult(),检查启动 Activity 的结果。
先来看 checkStartActivityResult 方法,主要是检查启动 Activity 的结果,有异常则抛出。例如下面代码中是一个典型的未找到启动 Activity 的异常,因为我们没有在 AndroidManifest 文件中声明我们的 Activity。

public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            ...
        }
    }

接着来看 ActivityTaskManager 的 getService 方法:

  • ActivityTaskManager
    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

这里是通过 Singleton 返回了一个 IActivityTaskManager 对象,Singleton 是一个单例的封装类,第一次调用它的get 方法时它会通过 create 方法来初始化一个 IActivityTaskManager,IActivityTaskManager 其实是一个 Binder 对象,负责应用和 ActivityTaskManagerService (以下简称 ATMS)直接的通信。
ATMS 运行在服务进程(system_server)中,Instrumentation 实现了应用和 ATMS 之间的通信,Activity 的启动就转移到了 ATMS 中:

  • ActivityTaskManagerService

ATMS 中 startActivity 方法调用了 startActivityAsUser 方法,startActivityAsUser 调用了 ActivityStarter 的 execute 方法。

    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) {
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
        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();
    }

getActivityStartController() 获取到 ActivityStarController 对象,调用 ActivityStarController 的 obtainStarter() 获取 ActivityStarter 对象,ActivityStart 设置一些需要传给应用进程的信息,然后调用了 ececute 方法。

  • ActivityStarter

execute 方法根据启动请求调用 startActivityMayWait 方法或者 startActivity 方法,直接来看 startActivity 方法,startActivity 方法调用了 startActivityUnchecked 方法,startActivityUnchecked 调用了 ActivityTask 的 sendActivityResultLocked 方法。

//ActivityStarter
    int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(...);
            } else {
                return startActivity(...);
            }
        } finally {
            onExecutionComplete();
        }
    }
    private ActivityStack mTargetStack;
//ActivityStarter#startActivityUnchecked()
    mTargetStack.startActivityResultLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);
  • ActivityTask

sendActivityResultLocked 方法通过 ActivityTaskManagerService 调用了 ClientLifecycleManager 的 scheduleTransaction 方法

    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            transaction.recycle();
        }
    }

scheduleTransaction 方法通过 ClientTransaction 的 schedule 方法调用了 IApplicationThread 的 scheduleTransaction 方法。

    private IApplicationThread mClient;
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }
  • IApplicationThread 和 ApplicationThread

IApplicationThread 继承了 IInterface 接口,它是一个 Binder 类型的接口,IApplicationThread 的最终实现类是 ActivityThread 的内部类 ApplicationThread。ApplicationThread 继承自 ApplicationThreadNative,ApplicationThreadNative 继承自 Binder 并实现来 IApplicationThread 接口。ApplicationThreadNative 的作用和使用 AIDL 时系统生成的类是一样,它的内部有一个 ApplicationThreadProxy 类,这个类也就是 AIDL 文件的代理类。综上所述,IApplicationThread 的实现类就是 ApplicationThreadNative,而 ApplicationThreadNative 被定义为了抽象类,那最终实现者就是 ApplicationThread。

  • ActivityThread

ApplicationThread 的 scheduleTransaction 方法调用了 ActivityThread 的 scheduleTransaction 方法,ActivityThread 继承自 ClientTransactionHandler,ClientTransactionHandler 是抽象类,它的 scheduleTransaction 方法中调用 sendMessage 方法发送了一条 EXECUTE_TRANSACTION 类型的消息,sendMessage 是抽象方法,ActivityThread 实现了该方法,ActivityThread 的 sendMessage 方法中将要发送的消息封装在 Message 中,通过 ActivityThread 的 H 对象 mH 执行了消息的发送,H 是 ActivityThread 的静态内部类,继承自 Handler,用于接收并处理来自其他线程的消息。

//ClientTransactionHandler
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    abstract void sendMessage(int what, Object obj);
//ActivityThread
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        ...
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

ActivityThread 中,H 收到 EXECUTE_TRANSACTION 类型的消息,调用 TransactionExecutor 的 execute 方法,execute 方法调用了 executeCallbacks 方法,executeCallbacks 中调用 LaunchActivityItem 的 execute 方法,LaunchActivityItem 继承自 ClientTransactionItem 并实现了 execute 方法,execute 方法调用了 ClientTransactionHandler 的 handleLaunchActivity 方法,ActivityThread 继承自 ClientTransactionHandler ,并实现了 handleLaunchActivity 方法,这里又回到了 ActivityThread 中的 handleLaunchActivity 方法内,handleLaunchActivity 方法调用了 performLaunchActivity 方法。

  • performLaunchActivity 方法:

1)从 ActivityClientRecord 中获取待启动 Activity 的启动信息;
2)调用 createBaseContextForActivity 方法创建 ContextImpl 对象,该方法中调用 ContextImpl 的 createActivityContext 方法创建 ContextImpl 对象;

    ContextImpl appContext = createBaseContextForActivity(r);

    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
       ...
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
        ...
        return appContext;
    }

3)调用 Instrumentation 的 newActivity 方法新建并加载 Activity,newActivity 方法中调用 AppComponentFactory 的 instantiateActivity方法,instantiateActivity 方法通过在 performLaunchActivity 方法中新建的 ClassLoader 加载新建的 Activity 类;

    activity = mInstrumentation.newActivity(cl,component.getClassName(),r.intent);

//Instrumentation
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }
//AppComponentFactory
    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity) cl.loadClass(className).newInstance();
    }

4)通过 LoadApk 的 makeApplication 方法创建一个 Application 对象;

   Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//r.packageInfo 就是 ActivityClientRecord 中存的 LoadApk 对象

5)调用 Activity 的 attach 方法,ContextImpl 通过 Activity 的 attach 方法来和 Activity 建立关联,除此之外,attach 方法还完成了 Window 的创建并建立自己和 Window 的关联,这样当 Window 接收到外部输入事件后就可以将事件传递给 Activity;

   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);
//Activity的attatch
        //将创建的 Activity 和 ContextImpl
        attachBaseContext(context); 建立关联
        //为新建的 Activity 创建 Window,用于接收到外部输入事件后将事件传给Activity
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

6)调用 Instrumentation 的 callActivityOnCreate 方法,callActivityOnCreate 方法调用 Activity 的 performCreate 方法,performCreate 调用 onCreate 方法。

    mInstrumentation.callActivityOnCreate(activity, r.state);
//Instrumentation
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
//Activity
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ...
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ...
    }

至此走完了从发起启动 Activity 的请求、Activity 的创建、Activity 的加载到最后调用 onCreate 方法的整个流程。这里只是分析整个的流程大概,涉及到启动模式等的细节没有去探讨。

4. 总结

4.1 重要类
  • Instrumentation:管理应用进程和系统进程之间的通信;
  • ActivityTaskManager:实现应用进程和运行在系统进程的 ActivityTaskManagerService 的通信;
  • ActivityTaskManagerService:负责管理activity;
  • ActivityStarter:负责启动模式,启动Flag相关处理;
  • ActivityStack:负责管理单独栈的 Activity 和其状态,即具体启动的执行等;
  • ApplicationThread(IApplicationThread):继承自 IApplicationThread,会在 ActivityTask 中调用,处理 Activity、Service、Broadcast 的创建等操作;
  • ActivityThread(ClientTransactionHandler):继承自 ClientTransactionHandler,管理应用进程中主线程,执行和调度 Activity、广播,处理来自 Activity 的任务请求;
  • ActivityClientRecord:保存和 Activity 相关的参数信息,还保存了和 Activity 关联的 Window 的信息;
4.2 完整流程图
Activity 启动流程图.png

5. 参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271