概述
本文基于android-28版本分析 startActivity
的启动流程。
整体流程
当我们点击手机桌面上的一个应用图标时,最终是通过 startActivity 方法去打开一个 Activity页面。
Android中每一个App都是一个进程。
startActivity的操作,必须先判定当前应用进程是否存在,如果不存在则需要先创建。
在这里我们必须清楚的是,Activity在整个安卓系统中不是孤立存在的,我们创建一个 应用A,在其中自定义一个Activity,这个Activity不一定就出现在 应用A的进程中,它可以通过 taskAffinity 出现在其他应用的Activity栈内。 由此可见,Activity并没有死死绑在 某一个App进程中。
startActivity的流程如图所示:
startActiviy的核心动作,其实只是把一个跳转意图Intent转发给了 AndroidSystem(更具体来说是ActivityManagerService,简称AMS),AMS 来解析这个Intent,然后根据情况看是否需要创建 应用进程,确保应用进程存在的情况下,再去把这个Activity放入该进程的Activity栈中。
步骤分析
整个流程分为三大步骤:
- Activity A ------> ActivityManagerService
- ActivityManagerService ------> ApplicationThread
- ApplicationThread ------> ActivityB
第一步 Activity A ------> ActivityManagerService
示意图
源码分析
-
执行
startActivity
后,转到startActivityForResult
,这个-1表示不需要关注跳转的结果。 -
跳转的实际动作,委托给了
Instrumention
。 注意:Instrumention
这个类,主要用于当前进程与系统进程的交互。你看它在startActivity
时传入了一个applicationThread
对象,它就是 我们自己app所在的进程,我们可以通过 这个application
对象实现 我们自己的进程与系统进程之间的通信,通信方式是 Binder AIDL 。 -
Instrumention
中的实际跳转动作
具体实现为,调用 AMS实例 (ActivityManager.getService()
)来执行系统级别的 startActivity跳转动作。
至此,startActivity的第一阶段,从当前app进程,工作重心,转移到了 系统进程中的AMS服务。
第二步 ActivityManagerService ------> ApplicationThread
首先剧透一下:每一个app,都会有 ApplicationThread实例保存在 系统进程中。当我们从ActivityA 跳转到 ActivityB,首先会通知到ActivityB所在进程的 ApplicationThread实例,最终由它去执行跳转动作。
这一步骤比较复杂,但是整体来说分为两个过程:
- 处理
intent
中的launchMode
和intent
中的flag标志位, 并通过结果生成一个ActivityB
的实例对象(ActivityRecord
) - 判断是否需要为目标
ActivityB
创建新的 进程(processRecord
) 和 新的Activity
任务栈 (TaskRecord
)
源码分析
- 以下是
ActivityManagerService.java
中 跟踪startActivity方法到达的最终代码位置:
它最终通过 obtainStarter
方法获取了 ActivityStarter
类型的对象,然后执行了 execute()
方法来执行跳转。 ActivityStarter
这个类专门用于Activity
的启动工作。主要作用 为 :解析Intent
,创建ActivityRecord
,如有必要还要创建TaskRecord
对象。
- 以下是
ActivityStarter
的startActivityMayWait
方法,
它其中调用了 mSuperVisor
的resolveActivity
方法。mSuperVisor
的类型是 ActivityStackSuperVisor
, 它负责Activity所处栈的管理。上图中还调用了它的 resloveIntent()
实际上是根据传入的intent
,调用了系统的PackageManagerService
来获取最佳Activity
。 有时候我们通过隐式Intent来启动Activity
时,系统中可能存在多个符合条件的Activity
,此时会弹出一个选择框,让用户选择启动哪一个Activity
。
- 在 startActivityMayWait() 中最后调用了 一个重载的startActivity(),它其中实际上走到了下图的代码:
startActivityUnchecked()
,返回值int
表示启动Activity的结果。 上图中3个关键代码分别代表的3个关键步骤:
1. computeLaunchingTaskFlags
计算Activity启动的Flag值
- 不同的Flag将会决定启动Activity放置在哪一个Task集合中
- 图中1处的 mInTask 是 TaskRecord 类型,此处为 null,表示 Activity要加入的栈不存在,因此需要判断是否需要新建Task。
- 图中2处的 mSourceRecord 是 ActivityRecord 类型,它是用来描述初始Activity,比如 由ActivityA启动了ActivityB,那么ActivityA就是 初始Activity。当我们用 Context或者Application启动Activity时,
mSourceRecord
就是null- 图中3处表示 初始Activity如果是在 SINGLE_INTANCE(Activity容量为1),那么必须添加NEW_TASK标识。
- 图中4处,如果我们启动Activity时设置了launchMode设置了 SINGLE_INTANCE 或者 SINGLE_TASK, 则也要创建一个新栈。
2. mTargetStack.startActivityLocked()
处理Task和Activity的入栈操作 图中的 insertTaskAtTop(),尝试将 task和Activity入栈。如果Activity是以 NEW_TASK的模式启动,或者 task堆栈中不存在该taskId,则task会重新入栈,并且放在栈的顶部。 需要注意的是,task先入栈,然后才是Activity入栈。 上图是 Task和Activity的关系,Task属于Activity的父集。ActivityStack是系统级别的容器,存放所有Activity,但是存放的过程有2个层次的,最大的是ActivityStack,接下来是 Task,而最小的是 Activity。
3. mSupervisor.resumeFocusedStackTopActivityLocked()
启动栈中顶部的Activity
mSuperVisor
的类型是ActivityStackSuperVisor
, 这个方法实际上走到了ActvityStack的resumeFocusedStackTopActivityLocked()
最终走到了ActivityStackSuperVisor
的startSpecificActivityLocked()
图中1处,根据进程名称和 applicaiton的uid来判定目标进程是否已经创建。图中2处,调用AMS创建Activity所在进程。
不管目标进程是否存在,最终都会调用,
realStartActivityLocked()
来启动Activity
。这个 realStartActivityLocked() 的实现,从android-28开始交给了事务(Transaction)来处理。 图中1处,创建了Activity启动事务,传入了
App.thread
对象。它是ApplicationThread
类型。这个ApplicationThread是用于处理进程间(Binder)通信的,它是 ActivityThread的内部类。图中2处,执行activity的启动事务。
Activity的启动事务是由
ClientLifecycleManager
来完成。 上图中的 transaction对象的创建,则是通过传入的app.thread来创建的。 所以 事务最终是调用了 ApplicationThread的 scheduleTranscation 来执行。
至此,startActivity的流程就从 AMS转移到了 另一个进程的ApplicationThread中。
第三步 ApplicationThread ------> ActivityB
刚才我们提到了 AMS
将 startActivity
的操作当做一个事务,传递给了ActivityB的ApplicationThread
的 scheduleTranscation
去完成. 后续的Activity生命周期过程都是 ApplicationThread这个内部类去完成的。
看到这个Stub,就应该能想起来,这是AIDL的一个抽象类。上图中的 scheduleTransaction
中,虽然是调用了 ActivityThread.this.schedueTransaction()
看着像是它在执行外部 ActivityThread
的某个过程. 但是实际上,过程在 ActivityThread 父类 ClientTransactionHandler
中,如下图:
通过handler发送了 EXECUTE_TRANSACTION
消息。 而这里的 大写 H
,是 ActivityThread
的内部类:
这里调用了 mTransactionExecutor的 execute方法,参数则是外部传入的 事务对象。
TransactionExecutor源代码如下:
execute()最终走到了 executeCallbacks()。上图中,对多个事务进行了遍历,逐个执行它们的 execute方法。这些callback是如何添加的呢? 其实是我们创建事务的时候,我们通过addCallback方法传入了 callback对象。如下图:
这个callback,其实是 LaunchActivityItem 类型的对象。 那么我们跟踪的重点就是 LaunchActivityItem 的 execute(),
终于到了和Activity生命周期相关的方法。
图中的 client是 ClientTransactionHandler
类型,实际实现类是ActivityThread
。
下图是 本次startActivity的重点内容 ActivityThread 源代码如下:
图中1处,初始化Activity的WindowManager。每一个Activity都会对应一个窗口。 图中2处,创建并显示Activity。 图中3处,通过反射创建 目标Activity对象。 图中4处,建立Activity与context之间的联系。创建PhoneWindow对象并与Activity进行关联。 图中5处,通过 Instrumention调用activity的onCreate方法。
至此,目标Activity已经成功创建并执行了生命周期方法。
总结
本文详细跟踪了 Activity 跳转的详细源码流程。
整个流程涉及到3个进程间通信:
- 进程A通过Binder调用了AMS的startActivity
- AMS通过一系列计算 构造目标intent,然后 ActivityStack与 ActivityStackSupervisor中处理了Task和Activity的入栈操作
- AMS通过 Binder机制 调用了 目标进程的 ApplicationThread方法来执行Activity的生命周期方法。ApplicationThrad是ActivityThread一个内部类,所以这一过程最终都执行到了 ActivityThread中。