APP启动流程

138 阅读3分钟

在进程之间,咱们都是通过binder来通信,四大组件与AMS来来回回的通信,要是能了解一下,就会发现Android一些东西都是能够联系起来,会有一种豁然开朗的感觉。
在APP侧,进行一些操作,比如AMS给Activity发送的所有消息,以及给其它三大组件发送的所有消息,都会在ActivityThread类的内部类大H经过。为啥要单独说呢,因为activity继承于context,而其他三大组件在Context中有抽象方法,具体在ContextImpl实现,在ConetextWrapper回调接口。 咱们可以具体了解一下APP的启动过程,留下印象即可:

APP启动流程

  1. Launcher->AMS:

Launcher向AMS发送一个跨进程通信,通过AMN/AMP,告诉AMS,我要启动别的App

Instrumentation的execStartActivity方法 Instrumentation绝对是Adnroid测试团队的最爱,因为它可以帮我们启动Activity。 回到我们的App启动过程来,在Instrumentation的execStartActivity方法中 Activity把数据借助Instrumentation,传递给ActivityManagerNative

我们每次跳转activity都会用到startActivity或者startActivityForResult,最终都会跳转到startActivityForResult

startActivityForResult->Instrumentation.execStartActivity->AMN.getDefault

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);
                // 这里就是我们的仪表盘Instrumentation了,帮助我们启动Activity
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // 源代码注释说了一大堆,翻译一下就是把这个activity隐藏了,直到下个activity finish收到结果
                mStartedActivity = true;
            }
            ......

AMN(ActivityManagerNative)有点像Stub,AMN继承于AMP,AMP(ActivityManagerProxy)类似于Proxy,他们都实现了IActivityManager接口(说它是aidl.java不过分吧)

  1. AMS->launcher:

client AMS发消息schedulePauseActivity()->Service launcher通过ApplicationThread类来实现来实现,这是ActivityThread的内部类

private class ApplicationThread extends IApplicationThread.Stub {
        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

        public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                boolean sync, int sendingUser, int processState) {

可以很清楚的看到,IApplicationThread类似于我们的aidl接口

  1. launcher->AMS

APT接收到来自AMS的消息后,就调用ActivityThread的sendMessage方法,向Launcher的主线程消息队列发送一个PAUSE_ACTIVITY消息。

前面说过,ActivityThread就是主线程中H发送消息,让launcher中的Activity进入Stop休眠

  1. AMS->APP

AMS调用Process.start(),指定ActivityThread的main函数作为入口

  1. APP -> AMS

到APP这边,就立即先创建ActivityThread(主线程),然后进入main函数里面,main()里面有蓝牙啊文件啊媒体啊等等的初始化,当然最重要的是创建了主线程的looper,网上说还有生成Application,我没找到。然后把ActivityThread对象发送给AMS进行记录

  1. AMS->APP:

AMS把传入的ActivityThread对象,转为一个ApplicationThread对象,用于以后和这个App跨进程通信,AMS传递APP中要启动的Activity

  1. APP

APP接收到消息,仍然在H的handleMessage方法的switch语句中处理,只不过,这次消息的类型是LAUNCH_ACTIVITY:

handleLaunchActivity方法都做哪些事呢?

  • 通过Instrumentation的newActivity方法,创建出来要启动的Activity实例。
  • 为这个Activity创建一个上下文Context对象,并与Activity进行关联。
  • 通过Instrumentation的callActivityOnCreate方法,执行Activity的onCreate方法,从而启动Activity。

同进程内:

1)ActivityA向AMS发送一个启动ActivityB的消息。

2)AMS保存ActivityB的信息,然后通知App进入onPaused。

3)ActivityA进入onPaused,然后通知AMS。

4)AMS发现ActivityB所在的进程就是ActivityA所在的进程,所以不需要重新启动新的进程,然后发送给App消息,启动ActivityB。

5)App启动ActivityB。