startActivity 启动过程分析课程

2020-07-13  本文已影响0人  NC丶脑补东

本届课程主要讲解了 startActivity 启动过程源码分析,引用的源码版本是 android-28。

假设 ActivityA 跳转到另一个App中的 ActivityB,过程如下图所示:

整个 startActivity 的流程分为 3 大部分,也涉及 3 个进程之间的交互:

  1. ActivityA --> ActivityManagerService(简称 AMS)
  2. ActivityManagerService --> ApplicationThread
  3. ApplicationThread --> Activity

ActivityA --> ActivityManagerService 阶段

这一过程并不复杂,用一张图表示具体过程如下:

Activity 的 startActivity

这里最终调用了 startActivityForResult 方法,传入的 -1 表示不需要获取 startActivity 的结果。

Activity 的 startActivityForResult

startActivityForResult 也很简单,调用 Instrumentation.execStartActivity 方法。剩下的交给 Instrumentation 类去处理。

解释说明:

Instrumentation 的 execStartActivity

这里获取了AMS,然后调用了startActivity方法。实际上这里就是通过 AIDL 来调用 AMS 的 startActivity 方法,至此,startActivity 的工作重心成功地从进程 A 转移到了系统进程 AMS 中。

ActivityManagerService --> ApplicationThread

接下来就看下在 AMS 中是如何一步一步执行到 B 进程的。

注:刚才在看 Instrumentation 的时候,讲过一个 ApplicationThread 类,这个类是负责进程间通信的,这里 AMS 最终其实就是调用了 B 进程中的一个 ApplicationThread 引用,从而间接地通知 B 进程进行相应操作。

相比于 startActivity-->AMS,AMS-->ApplicationThread 流程看起来复杂好多了,实际上这里面就干了 2 件事:

  1. 综合处理 launchMode 和 Intent 中的 Flag 标志位,并根据处理结果生成一个目标 Activity B 的对象(ActivityRecord)。
  2. 判断是否需要为目标 Activity B 创建一个新的进程(ProcessRecord)、新的任务栈(TaskRecord)。

AMS 的 startActivity

经过多个方法的调用,最终通过 obtainStarter 方法获取了 ActivityStarter 类型的对象,然后调用其 execute 方法。在 execute 方法中,会再次调用其内部的 startActivityMayWait 方法。

ActivityStarter 的 startActivityMayWait

ActivityStarter 这个类看名字就知道它专门负责一个 Activity 的启动操作。它的主要作用包括解析 Intent、创建 ActivityRecord、如果有可能还要创建 TaskRecord。startActivityMayWait 方法的部分实现如下:


这里的mSupervisor主要是负责 Activity 所处栈的管理类。

在上图中的 resolveIntent 中实际上是调用系统 PackageManagerService 来获取最佳 Activity。有时候我们通过隐式 Intent 启动 Activity 时,系统中可能存在多个 Activity 可以处理 Intent,此时会弹出一个选择框让用户选择具体需要打开哪一个 Activity 界面,就是此处的逻辑处理结果。

在 startActivityMayWait 方法中调用了一个重载的 startActivity 方法,而最终会调用的 ActivityStarter 中的 startActivityUnchecked 方法来获取启动 Activity 的结果。

ActivityStarter 的 startActivityUnchecked

computeLaunchingTaskFlags 方法具体如下:

这个方法的主要作用是计算启动 Activity 的 Flag,不同的 Flag 决定了启动 Activity 最终会被放置到哪一个 Task 集合中。

ActivityStackSupervisor 的 startActivityLocked

方法中会调用 insertTaskAtTop 方法尝试将 Task 和 Activity 入栈。如果 Activity 是以 newTask 的模式启动或者 TASK 堆栈中不存在该 Task id,则 Task 会重新入栈,并且放在栈的顶部。需要注意的是:Task 先入栈,之后才是 Activity 入栈,它们是包含关系。

这里一下子涌出了好几个概念 Stack、Task、Activity,其实它们都是在 AMS 内部维护的数据结构,可以用一张图来描述它们之间的关系。


如:这次课程是 ActivityA 跳转到另一个App中的 ActivityB,所以如果ActivityB所在的App没有启动。这里会先在AMS中的 ActivityStackSupervisor 中创建 ActivityStack,并且通过创建的 ActivityStack 来管理 TaskRecord。Task会入栈,然后Activity入栈,不同启动模式所放入的栈的方式也是不一样的。如果是 singleTask 或 singleInstance 启动模式,则会另外创建TaskRecord,并添加到 ActivityStack 进行管理。

ActivityStack 的 resumeFocusedStackTopActivityLocked

经过一系列调用,最终代码又回到了 ActivityStackSupervisor 中的 startSpecificActivityLocked 方法。

ActivityStackSupervisor 的 startSpecificActivityLocked

解释说明:

不管是目标进程已经存在还是新建目标进程,最终都会调用图中红线标记的 realStartActivityLocked 方法来执行启动 Activity 的操作。

ActivityStackSupervisor 的 realStartActivityLocked

这个方法在 android-27 和 android-28 版本的区别很大,从 android-28 开始 Activity 的启动交给了事务(Transaction)来完成。

Activity 启动事务的执行是由 ClientLifecycleManager 来完成的,具体代码如下:

可以看出实际上是调用了启动事务 ClientTransaction 的 schedule 方法,而这个 transaction 实际上是在创建 ClientTransaction 时传入的 app.thread 对象,也就是 ApplicationThread。如下所示:

解释说明:

到这为止 startActivity 操作就成功地从 AMS 转移到了另一个进程 B 中的ApplicationThread中,剩下的就是 AMS 通过进程间通信机制通知 ApplicationThread 执行 ActivityB 的生命周期方法。而这里的app.thread也是在startSpecificActivityLocked中创建进程时所创建的。

ApplicationThread -> Activity

在 ClientLifecycleManager 中会调用 ClientTransaction的schedule() 方法


而 mClient 是一个 IApplicationThread 接口类型,具体实现是 ActivityThread 的内部类 ApplicationThread。因此后续执行 Activity 生命周期的过程都是由 ApplicationThread 指导完成的,scheduleTransaction 方法如下:



可以看出,这里还是调用了ActivityThread 的 scheduleTransaction 方法。但是这个方法实际上是在 ActivityThread 的父类 ClientTransactionHandler 中实现,具体如下:

调用 sendMessage 方法,向 Handler 中发送了一个 EXECUTE_TRANSACTION 的消息,并且 Message 中的 obj 就是启动 Activity 的事务对象。而这个 Handler 的具体实现是 ActivityThread 中的 mH 对象。具体如下:

最终调用了事务的 execute 方法,execute 方法如下:

在 executeCallback 方法中,会遍历事务中的 callback 并执行 execute 方法

之前添加callback的地方

在创建 ClientTransaction 时,通过 addCallback 方法传入了 Callback 参数,从图中可以看出其实是一个 LauncherActivityItem 类型的对象。

LaunchActivityItem 的 execute()

终于到了跟 Activity 生命周期相关的方法了,图中 client 是 ClientTransationHandler 类型,实际实现类就是 ActivityThread。因此最终方法又回到了 ActivityThread。

ActivityThread 的 handleLaunchActivity

这是一个比较重要的方法,Activity 的生命周期方法就是在这个方法中有序执行,具体如下:

解释说明:

至此,目标 Activity 已经被成功创建并执行生命周期方法。

上一篇 下一篇

猜你喜欢

热点阅读