likes
comments
collection
share

十九、startActivity过程分析

作者站长头像
站长
· 阅读数 3

概述

本文基于android-28版本分析 startActivity 的启动流程。

整体流程

当我们点击手机桌面上的一个应用图标时,最终是通过 startActivity 方法去打开一个 Activity页面。

Android中每一个App都是一个进程。

startActivity的操作,必须先判定当前应用进程是否存在,如果不存在则需要先创建。

在这里我们必须清楚的是,Activity在整个安卓系统中不是孤立存在的,我们创建一个 应用A,在其中自定义一个Activity,这个Activity不一定就出现在 应用A的进程中,它可以通过 taskAffinity 出现在其他应用的Activity栈内。 由此可见,Activity并没有死死绑在 某一个App进程中。

startActivity的流程如图所示:

十九、startActivity过程分析

startActiviy的核心动作,其实只是把一个跳转意图Intent转发给了 AndroidSystem(更具体来说是ActivityManagerService,简称AMS),AMS 来解析这个Intent,然后根据情况看是否需要创建 应用进程,确保应用进程存在的情况下,再去把这个Activity放入该进程的Activity栈中。

步骤分析

整个流程分为三大步骤:

  • Activity A ------> ActivityManagerService
  • ActivityManagerService ------> ApplicationThread
  • ApplicationThread ------> ActivityB

第一步 Activity A ------> ActivityManagerService

示意图

十九、startActivity过程分析

源码分析

  1. 执行 startActivity 后,转到 startActivityForResult,这个-1表示不需要关注跳转的结果。 十九、startActivity过程分析

  2. 跳转的实际动作,委托给了 Instrumention 。 注意:Instrumention这个类,主要用于当前进程与系统进程的交互。你看它在 startActivity时传入了一个 applicationThread 对象,它就是 我们自己app所在的进程,我们可以通过 这个application对象实现 我们自己的进程与系统进程之间的通信,通信方式是 Binder AIDL 。 十九、startActivity过程分析

  3. Instrumention 中的实际跳转动作

十九、startActivity过程分析 具体实现为,调用 AMS实例 (ActivityManager.getService())来执行系统级别的 startActivity跳转动作。

至此,startActivity的第一阶段,从当前app进程,工作重心,转移到了 系统进程中的AMS服务。

第二步 ActivityManagerService ------> ApplicationThread

首先剧透一下:每一个app,都会有 ApplicationThread实例保存在 系统进程中。当我们从ActivityA 跳转到 ActivityB,首先会通知到ActivityB所在进程的 ApplicationThread实例,最终由它去执行跳转动作。

这一步骤比较复杂,但是整体来说分为两个过程:

  1. 处理intent中的 launchModeintent中的flag标志位, 并通过结果生成一个 ActivityB的实例对象(ActivityRecord
  2. 判断是否需要为目标ActivityB创建新的 进程(processRecord) 和 新的Activity任务栈 (TaskRecord

源码分析

  • 以下是 ActivityManagerService.java中 跟踪startActivity方法到达的最终代码位置:

十九、startActivity过程分析 它最终通过 obtainStarter方法获取了 ActivityStarter类型的对象,然后执行了 execute() 方法来执行跳转。 ActivityStarter这个类专门用于Activity的启动工作。主要作用 为 :解析Intent创建ActivityRecord,如有必要还要创建TaskRecord对象。

  • 以下是 ActivityStarterstartActivityMayWait方法,

十九、startActivity过程分析

它其中调用了 mSuperVisorresolveActivity 方法。mSuperVisor 的类型是 ActivityStackSuperVisor, 它负责Activity所处栈的管理。上图中还调用了它的 resloveIntent()实际上是根据传入的intent,调用了系统的PackageManagerService来获取最佳Activity。 有时候我们通过隐式Intent来启动Activity时,系统中可能存在多个符合条件的Activity,此时会弹出一个选择框,让用户选择启动哪一个Activity

  • 在 startActivityMayWait() 中最后调用了 一个重载的startActivity(),它其中实际上走到了下图的代码: 十九、startActivity过程分析 startActivityUnchecked(),返回值int表示启动Activity的结果。 上图中3个关键代码分别代表的3个关键步骤:

1. computeLaunchingTaskFlags

计算Activity启动的Flag值 十九、startActivity过程分析

  • 不同的Flag将会决定启动Activity放置在哪一个Task集合中
  • 图中1处的 mInTaskTaskRecord 类型,此处为 null,表示 Activity要加入的栈不存在,因此需要判断是否需要新建Task。
  • 图中2处的 mSourceRecordActivityRecord 类型,它是用来描述初始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的入栈操作 十九、startActivity过程分析 图中的 insertTaskAtTop(),尝试将 task和Activity入栈。如果Activity是以 NEW_TASK的模式启动,或者 task堆栈中不存在该taskId,则task会重新入栈,并且放在栈的顶部。 需要注意的是,task先入栈,然后才是Activity入栈。 十九、startActivity过程分析 上图是 Task和Activity的关系,Task属于Activity的父集。ActivityStack是系统级别的容器,存放所有Activity,但是存放的过程有2个层次的,最大的是ActivityStack,接下来是 Task,而最小的是 Activity。

3. mSupervisor.resumeFocusedStackTopActivityLocked()

启动栈中顶部的Activity

mSuperVisor 的类型是 ActivityStackSuperVisor, 这个方法实际上走到了ActvityStack的resumeFocusedStackTopActivityLocked() 十九、startActivity过程分析 最终走到了 ActivityStackSuperVisorstartSpecificActivityLocked() 十九、startActivity过程分析 图中1处,根据进程名称和 applicaiton的uid来判定目标进程是否已经创建。

图中2处,调用AMS创建Activity所在进程。

不管目标进程是否存在,最终都会调用, realStartActivityLocked() 来启动Activity

这个 realStartActivityLocked() 的实现,从android-28开始交给了事务(Transaction)来处理。 十九、startActivity过程分析 图中1处,创建了Activity启动事务,传入了App.thread对象。它是ApplicationThread类型。这个ApplicationThread是用于处理进程间(Binder)通信的,它是 ActivityThread的内部类。

图中2处,执行activity的启动事务。

Activity的启动事务是由 ClientLifecycleManager 来完成。 十九、startActivity过程分析 上图中的 transaction对象的创建,则是通过传入的app.thread来创建的。 十九、startActivity过程分析 所以 事务最终是调用了 ApplicationThread的 scheduleTranscation 来执行。

至此,startActivity的流程就从 AMS转移到了 另一个进程的ApplicationThread中。

第三步 ApplicationThread ------> ActivityB

刚才我们提到了 AMSstartActivity 的操作当做一个事务,传递给了ActivityB的ApplicationThreadscheduleTranscation 去完成. 后续的Activity生命周期过程都是 ApplicationThread这个内部类去完成的。

十九、startActivity过程分析

看到这个Stub,就应该能想起来,这是AIDL的一个抽象类。上图中的 scheduleTransaction 中,虽然是调用了 ActivityThread.this.schedueTransaction() 看着像是它在执行外部 ActivityThread的某个过程. 但是实际上,过程在 ActivityThread 父类 ClientTransactionHandler中,如下图:

十九、startActivity过程分析

通过handler发送了 EXECUTE_TRANSACTION 消息。 而这里的 大写 H,是 ActivityThread的内部类:

十九、startActivity过程分析 这里调用了 mTransactionExecutor的 execute方法,参数则是外部传入的 事务对象。

TransactionExecutor源代码如下: 十九、startActivity过程分析

execute()最终走到了 executeCallbacks()。上图中,对多个事务进行了遍历,逐个执行它们的 execute方法。这些callback是如何添加的呢? 其实是我们创建事务的时候,我们通过addCallback方法传入了 callback对象。如下图:

十九、startActivity过程分析

这个callback,其实是 LaunchActivityItem 类型的对象。 那么我们跟踪的重点就是 LaunchActivityItem 的 execute(),

十九、startActivity过程分析

终于到了和Activity生命周期相关的方法。

图中的 client是 ClientTransactionHandler类型,实际实现类是ActivityThread

下图是 本次startActivity的重点内容 ActivityThread 源代码如下: 十九、startActivity过程分析

图中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中。