深入理解四大组件(二)Android8.0 根 Activity 的启动过程(下)

上篇链接:深入理解四大组件(一)Android8.0 根 Activity 的启动过程(上)

1. ActivityThread 启动 Activity 的过程

通过上篇知识点,我们知道目前的代码逻辑运行在应用程序进程中。先来查看 ActivityThread 启动 Activity 过程的时序图,如图所示:

ActivityThread 启动 Activity 过程的时序图

接着查看 ApplicationThread 的 scheduleLaunchActivity 方法,其中 ApplicationThread 是 ActivityThread 的内部类,应用程序进程创建后会运行代表主线程的实例 ActivityThread,它管理着当前应用程序进程的主线程。ApplicationThread 的 scheduleLaunchActivity 方法如下所示:
frameworks/base/core/java/android/app/ActivityThread.java

        @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 pendingResults, List pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
                  updateProcessState(procState, false);
                  ActivityClientRecord r = new ActivityClientRecord();
                  r.token = token;
                  r.ident = ident;
                  r.intent = intent;
                  r.referrer = referrer;
                 ···
                  updatePendingConfiguration(curConfig);
                  sendMessage(H.LAUNCH_ACTIVITY, r);
        }

scheduleLaunchActivity 方法将启动 Activity 的参数封装成 ActivityClientRecord,sendMessage 方法向 H 类发送类型为 LAUNCH_ACTIVITY 的消息,并将 ActivityClientRecord 传递过去,sendMessage 方法有多个重载方法,最终调用的 sendMessage 方法如下所示:
frameworks/base/core/java/android/app/ActivityThread.java

    private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
        if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                        "seq= " + seq);
        Message msg = Message.obtain();
        msg.what = what;
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = obj;
        args.argi1 = arg1;
        args.argi2 = arg2;
        args.argi3 = seq;
        msg.obj = args;
        mH.sendMessage(msg);
    }

这里的 mH 指的是 H,它是 ActivityThread 的内部类并继承自 Handler,是应用程序进程中主线程的消息管理类。因为 ApplicationThread 是一个 Binder,它的调用逻辑运行在 Binder 线程池中,所以这里需要用 H 将代码的逻辑切换到主线程中。H 的代码如下所示:
frameworks/base/core/java/android/app/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) {
          if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
          switch (msg.what) {
              case LAUNCH_ACTIVITY: {
                  Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                  final ActivityClientRecord r = (ActivityClientRecord) msg.obj;  //1
                  r.packageInfo = getPackageInfoNoCheck(
                          r.activityInfo.applicationInfo, r.compatInfo);  //2
                  handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");  //3
                  Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
              case RELAUNCH_ACTIVITY: {
                  Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                  ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                  handleRelaunchActivity(r);
                  Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
            ...
}

查看 H 的 handleMessage 方法中对 LAUNCH_ACTIVITY 的处理,在注释 1 处将传过来的 msg 的成员变量 obj 转换为 ActivityClientRecord。在 注释 2 处通过 getPackageInfoNoCheck 方法获得 LoadedApk 类型的对象并赋值给 ActivityClientRecord 的成员变量 packageInfo。应用程序进程要启动 Activity 时需要将该 Activity 所属的 APK 加载进来,而 LoadApk 就是用来描述已加载的 APK 文件的。在注释 3 处调用 handleLaunchActivity 方法,代码如下所示:
frameworks/base/core/java/android/app/ActivityThread.java

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    WindowManagerGlobal.initialize();
    //启动Activity
    Activity a = performLaunchActivity(r, customIntent);  //1
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        //将Activity的状态置为Resume
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);  //2
        if (!r.activity.mFinished && r.startsNotResumed) {
            performPauseActivityIfNeeded(r, reason);
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        try {
            //停止Activity启动
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

注释 1 处的 performLaunchActivity 方法用来启动 Activity,注释 2 处的代码用来将 Activity 的状态设置为 Resume。如果该 Activity 为 null 则会通知 AMS 停止启动 Activity。下面来查看 performLaunchActivity 方法做了什么:
frameworks/base/core/java/android/app/ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       //获取ActivityInfo类
       ActivityInfo aInfo = r.activityInfo;  //1
       if (r.packageInfo == null) {
       //获取APK文件的描述类LoadedApk
           r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                   Context.CONTEXT_INCLUDE_CODE);  //2
       }

       ComponentName component = r.intent.getComponent();  //3
       ...
       //创建要启动Activity的上下文环境
       ContextImpl appContext = createBaseContextForActivity(r);  //4
       Activity activity = null;
       try {
           java.lang.ClassLoader cl = appContext.getClassLoader();
           //用类加载器来创建该Activity的实例
           activity = mInstrumentation.newActivity(
                   cl, component.getClassName(), r.intent);  //5
         ...
       } catch (Exception e) {
         ...
       }

       try {
           //创建Application
           Application app = r.packageInfo.makeApplication(false, mInstrumentation);  //6
           ...
           if (activity != null) {
              ...
               /**
               * 7 初始化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);
              ...
               if (r.isPersistable()) {
                   mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);  //8
               } else {
                   mInstrumentation.callActivityOnCreate(activity, r.state);
               }
              ...
           }
           r.paused = true;
           mActivities.put(r.token, r);
       } catch (SuperNotCalledException e) {
           throw e;
       } catch (Exception e) {
         ...
       }
       return activity;
   }

注释 1 处用来获取 ActivityInfo,用于储存代码以及 AndroidManifes 设置的 Activity 和 Receiver 节点信息,比如 Activity 的 theme 和 launchMode。在注释 2 处获取 APK 文件的描述类 LoadedApk。在注释 3 处获取要启动的 Activity 的 ComponentName 类,在 ComponentName 类中保存了该 Activity 的包名和类名。注释 4 处用来创建要启动 Activity 的上下文环境。注释 5 处根据 ComponentName 中储存的 Activity 类名,用类加载器来创建该 Activity 的实例。注释 6 处用来创建 Application,makeApplication 方法内部会调用 Application 的 onCreate 方法。注释 7 处调用 Activity 的 attach 方法初始化 Activity,在 attach 方法中会创建 Window 对象(PhoneWindow)并与 Activity 自身进行关联。在注释 8 处调用 Instrumentation 的 callActivityOnCreate 方法来启动 Activity,如下所示:
frameworks/base/core/java/android/app/Instrumentation.java

public void callActivityOnCreate(Activity activity, Bundle icicle,
          PersistableBundle persistentState) {
      prePerformCreate(activity);
      activity.performCreate(icicle, persistentState);  //1
      postPerformCreate(activity);
  }

注释 1 处调用了 Activity 的 performCreate 方法,代码如下所示:
frameworks/base/core/java/android/app/Activity.java

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
      restoreHasCurrentPermissionRequest(icicle);
      onCreate(icicle, persistentState);
      mActivityTransitionState.readState(icicle);
      performCreateCommon();
  }

在 performCreate 方法中调用 Activity 的 onCreate 方法,讲到这里,根 Activity 就启动了,即应用程序就启动了。根 Activity 启动过程就讲到这里,下面我们来学习根 Activity 启动过程中涉及的进程。

2. 根 Activity 启动过程中涉及的进程

根 Activity 启动过程中会涉及 4 个进程,分别是 Zygote 进程、Launcher 进程、AMS 所在的进程(SystemServer进程)、应用程序进程。它们之间的关系如图所示:


根 Activity 启动过程中涉及的进程之间的关系

首先 Launcher 进程向 AMS 请求创建根进程 Activity,AMS 会判断根 Activity 所需的应用程序进程是否存在并启动,如果不存在就会请求 Zygote 进程创建应用程序进程。应用程序进程启动后,AMS 会请求创建应用程序进程并启动根 Activity。其中步骤 2 采用的是 Socket 通信,步骤 1 和步骤 4 采用的是 Binder 通信。为了更好理解,下面给出这个 4 个进程调用的时序图,如图所示:


根 Activity 启动过程中进程调用时序图

总结

如果普通 Activity 启动过程会涉及几个进程呢?答案是两个,AMS 所在进程和应用程序进程。实际上理解了根 Activity 的启动过程(根 Activity 的 onCreate 过程),根 Activity 和普通 Activity 其他生命周期状态(比如 onStart、onResume 等)过程也会很轻松掌握,这些知识点都是触类旁通的。这两篇的文章讲解了根 Activity 的启动过程,下面我们对其他四大组件的启动过程进行学习!

学习资料主要来源于《Android进阶解密》

你可能感兴趣的:(深入理解四大组件(二)Android8.0 根 Activity 的启动过程(下))