目录

再再再看 startActivity 启动流程

前言

最近遇到了一个有意思的问题,为了让首页更快的展示出来,将首页的请求提前到了 Application onCreate 阶段。但是带来了一个问题,请求的频次大大增加了,且对于后端来说,首页的请求还是比较消耗资源的。

为什么请求频次会增加呢?因为可能有人拉起一些主进程的 Service(工程中集成了一些三方 sdk,存在一些 exported 的 Service) 导致 Application onCreate 被执行了,但是 Activity 却没有被创建,或者直接拉起了非首页的 Activity 等各种情况

那么,问题就成了:我们如何在 Application 阶段知道当前要启动的是哪个 Activity

通过一番搜索,并没有找到任何答案

如果你有好的办法,也请共享一下

下面提供一种我摸索的方案,但是理论上有获取失败的概率

Activity 的启动流程

有关 Activity 启动流程,太多人写过,这里就不赘述

思考几个问题

  1. startActivity 时,如果应用进程还未创建,那一定要创建进程的。创建完应用进程,已经处于应用进程中,后续又是怎么回到 AMS 进程的?

  2. Application onCreate 发生在哪个阶段?

  3. Activity onCreate 发生在哪个阶段?

搞清楚这几个问题,基本就可以知道如何在 Application onCreate 阶段获取到当前要启动的 Activity 是谁

应用进程未启动时的几次主要 IPC 调用

以下分析基于 Android 13,省略了很多细节,只关注 Application 和 Activity 的 onCreate 阶段

/img/in-post/application_activity.png

如果你对这个过程比较了解的话,应该已经看出怎么处理之前提到的问题了

我们仔细看,AMS 处理 attachApplication 的逻辑,它前后进行了两次 IPC 调用

第一次,调用 bindApplication() 触发 Application 的 onCreate 方法

第二次,调用 scheduleTransaction() 触发 Activity 的 onCreate 方法

这两个 IPC 调用,都是通过 post message 到 ActivityThread 的 H handler 处理的

那我们就有机会在处理 Application onCreate 的时候,去获取到 MQ 里面的 message 进而拿到 LaunchActivityItem 拿到 Intent,进而可以获取到启动到的目标 Activity

这里有个小问题

  1. Activity 启动各个版本不太一致,需要版本适配
  2. LaunchAcitivityItem 应用进程并没有加载这个 class,反射获取时候会抛出 ClassNotFoundException,需要我们手动加载,Class.forName(“android.app.servertransaction.LaunchActivityItem”)

获取失败的情况

由上面的分析我们也知道,如果 AMS attachApplication 阶段往应用进程发起的两次 IPC 调用间隔时间很长,长过了应用进程处理 Application onCreate 的时间

也就是说,我们在执行 Application onCreate 的时候,AMS 遇到了问题,比如系统进程卡主了?scheduleTransaction 一直没有被调用,那么应用进程的 MQ 里并不存在我们想要找的 activity 启动的 message,进而获取失败

或者,Application onCreate 执行的极快无比(但是可能性不大,国内互联网大厂的 application 都很重,我们可以将获取逻辑放在 application onCreate 的最后阶段),同样的原理,会获取失败

总结

示例代码:LaunchActivity

上述方法,在一定程度上可以在 Application onCreate 阶段获取到要启动的 Activity,但是不一定稳定,有理论上获取不到的概率

如果你有更好的办法,请一定告诉我