Activity启动流程

页面开发时需要使用Acitivty作为的UI载体,官方对于Acitivty给开发者开放了很多生命周期。本文分析启动Acitivty所经历的流程。

通过源码分析我们要解决以下问题:

  1. Acitivty是如何创建的?
  2. Acitivty声明周期的执行,如onCreate被谁调用?
  3. Activity启动流程涉及哪些环节?

Activity启动

通过指定Intent,调用startActivity可以开启一个新的Activity,并且在Activity的onCreate执行时进行初始化等业务逻辑。

时序图

通过分析源码,我们提取核心的调用流程,其中深红色箭头代表发生了跨进程调用

核心环节分析

由于Android的源码一直在迭代,Framework的内部细节会有些变化,但是主体流程变化不大。 比如ActivityManagerNative这个类在API 28,27,26的源码中已经废弃,源码也注释了相应的替代接口。

类似废弃的还有:

  • ActivityManagerProxy删除
  • ActivityManagerNative废弃
  • ApplicationThreadProxy删除

我们把整个流程精简一下,核心步骤如下图:

ContextWrapper, ContextImpl

作为顶层入口,提供了Activity启动的调用API,如startActivity, startActivityForResult;

ActivityManagerService

系统服务,经常被称作AMS,App调用AMS是通过Binder机制实现的,AMS是系统服务。在这里提供了startActivity服务,我们通过Context的api启动Activity最终是将消息发送给了AMS,执行对应的跨进程操作。

ActivityStartController、ActivityStart

由于执行Activity启动是一个相对复杂的动作,包括对Intent的flag的判定,Activity从属Task的判断,已经当前Task内是否有Activity,置顶等等,这些都依赖了大量的参数,参数列表就很长。在我们分析的API 28版本中,系统会用建造者模式,创建对应的ActivityStart来处理启动参数。 比如:

mActivityStartController.obtainStarter(intent, "startActivityAsUser")
    .setCaller(caller)
    .setCallingPackage(callingPackage)
    .setResolvedType(resolvedType)
    .setResultTo(resultTo)
    .setResultWho(resultWho)
    .setRequestCode(requestCode)
    .setStartFlags(startFlags)
    .setProfilerInfo(profilerInfo)
    .setActivityOptions(bOptions)
    .setMayWait(userId)
    .execute();

ActivityStack、ActivityStackSupervisor

ActivityStart中经过层层判定转发,最后会将控制权转移到Stack这边。

  • ActivityStack管理了Activity的状态,他持有AMS引用,也持有ActivityStackSupervisor引用
  • ActivityStackSupervisor是ActivityStack的管理类,他也持有AMS,并且持有多份ActivityStack对象
  • ActivityStackSupervisor最后会通过AMS发起Transaction动作,Transaction的具体实现有很多,执行后触发Callback,其中一个就是代表启动Activity的LaunchItem

ActivityThread、ClientTransactionHandler

这两个是子类与父类关系,ActivityThread实现了父类的一些API,比如handleLaunchActivity,类似API还有:

  • handleResumeActivity
  • handlePauseActivity
  • handleStopActivity
  • handleDestroyActivity
  • handleActivityConfigurationChanged
  • handleNewIntent
  • handleRelaunchActivity
  • sendMessage
  • updatePendingConfiguration

基本上覆盖到了Activity的生命周期。

onActivityResult流程

Activity启动发起后,通过Binder最终交由system进程中的AMS来完成。

  • 启动Acitivty的动作,经历了ActivityManagerService,简称AMS,ActivityStackSupervisor,通过跨进程Binder调用,将创建Activity的消息给到了目标App的进程。
  • 目标App进程唤起后,最终由ActivityThread.H处理一个Acitivty Create消息,然后从消息携带的ActivityClientRecord中构造出Acitivty信息,用反射调用无参构造函数;最后执行Acitivty实例的onCreate方法。
  • 在执行Activity.onCreate前有一段对Application创建检查的逻辑,保证一个App进程必须有一个Application实例,除此之外还有创建ContextImpl和attach的相关逻辑。

在启动Activity的API执行后,还有一段对返回值的校验动作,

  • 在ActivityThread.sendActivityResult执行后,通过H(Handler)内执行了transaction消息,调用了ActivityResultItem的execute方法;

  • 该对象持有ActivityThread引用,执行Result分发逻辑,进一步调用Activity的dispatchActivityResult方法,该方法会执行我们平时复写的onActivityResult

调用关系如下:

  1. ActivityThread.sendActivityResult
  2. ClientTransactionHandler.scheduleTransaction
  3. ActivityThread.H => EXECUTE_TRANSACTION
  4. android.app.servertransaction.TransactionExecutor.execute
  5. ClientTransactionItem.execute
  6. 注意在这个场景下,ClientTransactionItem的实现类就是ActivityResultItem,所以执行的是ActivityResultItem.execute
  7. ActivityThread.handleSendResult
  8. ActivityThread.deliverResults
  9. Activity.dispatchActivityResult
  10. Activity.onActivityResult

小结

通过分析Activity启动流程,可以发现他的嵌套转发虽然很多,很深,但是大的就是套路模式。现在我们解答一下开篇的疑问:

  1. Acitivty是如何创建的?

Activity的创建,首先经过了AMS转发,实现了不同进程间的切换,最终由Acitivty的目标进程的ActivityThread进行处理,具体过程为,通过Transaction执行了handleLaunchActivity方法,然后利用Classloader,执行Instrumentation.newActivty实例化了Activity对象

  1. Acitivty声明周期的执行,如onCreate被谁调用?

在Activity实例化后,会执行Activity的attach,setTheme,performCreate,接着内部执行到了onCreate方法

  1. Activity启动流程涉及哪些环节?
  • 发起App,调用Context的接口,将请求通过Binder机制发送到系统服务AMS处理;
  • AMS接受到请求后根据目标App的存活情况,新页面的参数配置,进行一系列的准备;
  • AMS最终将创建Activity的任务转发给目标App进程,由目标进程的ActivityThread信息Activity的构造和生命周期的执行;

参考

powered by Gitbook最近更新 2019-10-25

results matching ""

    No results matching ""