Android

来源:互联网 发布:暗黑3数据挖掘者在哪 编辑:程序博客网 时间:2024/06/05 15:55

Android - Activity 启动过程

概述

Activity 是四大组件之一,在应用启动的时候,一般情况下首先启动的就是 Activity。 下面就来讨论下 Activity 是如何启动的?

本篇文章需要 Binder 进程间通讯的知识,不了解的请先看下 Binder 进程间通讯

启动流程

Activity 的整体启动流程如图所示:

这里写图片描述

下面是图中步骤的详细分析。

1. 发送 START_ACTIVITY_TRANSACTION 命令

Intent intent = new Intent(this, TestActivity.class);startActivity(intent);

这段代码大家已经很熟悉,通过追踪代码可以发现最后调用了 startActivityForResult()。

  • startActivityForResult(intent, -1)

默认 requestCode = -1,也可通过调用 startActivityForResult() 传入 requestCode。 然后通过 MainThread 获取到 ApplicationThread 传入下面方法。

  • execStartActivity()

通过 ActivityManagerNative.getDefault() 获取到 ActivityManagerService 的代理为进程通讯作准备。

  • ActivityManagerProxy.startActivity()

调用代理对象的 startActivity() 方法,发送 START_ACTIVITY_TRANSACTION 命令。

2. 发送创建进程的请求

在 system_server 进程中的服务端 ActivityManagerService 收到 START_ACTIVITY_TRANSACTION 命令后进行处理,调用 startActivity() 方法。

  • ActivityManagerService.startActivity() -> startActivityAsUser(intent, requestCode, userId)

通过 UserHandle.getCallingUserId() 获取到 userId 并调用 startActivityAsUser() 方法。

  • ActivityStackSupervisor.startActivityMayWait() -> resolveActivity()

通过 intent 创建新的 intent 对象,即使之前 intent 被修改也不受影响。 然后调用 resolveActivity()。

然后通过层层调用获取到 ApplicationPackageManager 对象。

  • PackageManagerService.resolveIntent() -> queryIntentActivities()

获取 intent 所指向的 Activity 信息,并保存到 Intent 对象。

  • PackageManagerService.chooseBestActivity()

当存在多个满足条件的 Activity 则会弹框让用户来选择。

  • ActivityStackSupervisor.startActivityLocked()

获取到调用者的进程信息。 通过 Intent.FLAG_ACTIVITY_FORWARD_RESULT 判断是否需要进行 startActivityForResult 处理。 检查调用者是否有权限来调用指定的 Activity。 创建 ActivityRecord 对象,并检查是否运行 App 切换。

  • ActivityStackSupervisor.startActivityUncheckedLocked() -> startActivityLocked()

进行对 launchMode 的处理,创建 Task 等操作。 启动 Activity 所在进程,已存在则直接 onResume(),不存在则创建 Activity 并处理是否触发 onNewIntent()。

launchMode 可参考 Activity 启动模式

  • ActivityStack.resumeTopActivityInnerLocked()

找到 resume 状态的 Activity,执行 startPausingLocked() 暂停该 Activity,同时暂停所有处于后台栈的 Activity,找不到 resume 状态的 Activity 则回桌面。

如果需要启动的 Activity 进程已存在,直接设置 Activity 状态为 resumed。 调用下面方法。

  • ActivityStackSupervisor.startSpecificActivityLocked()

进程存在调用 realStartActivityLocked() 启动 Activity,进程不存在则调用下面方法。

3. fork 新进程

  • ActivityManagerService.startProcessLocked()

进程不存在请求 Zygote 创建新进程。 创建成功后切换到新进程。

切换至 App 进程

进入 app 进程后将 ActivityThread 类加载到新进程,并调用 ActivityThread.main() 方法

  • ActivityThread.main()

创建主线程的 Looper 对象,创建 ActivityThread 对象,ActivityThread.attach() 建立 Binder 通道,开启 Looper.loop() 消息循环。

  • ActivityThread.attach()

开启虚拟机各项功能,创建 ActivityManagerProxy 对象,调用基于 IActivityManager 接口的 Binder 通道 ActivityManagerProxy.attachApplication()。

  • ActivityManagerProxy.attachApplication()

发送 ATTACH_APPLICATION_TRANSACTION 命令

4. 发送 ATTACH_APPLICATION_TRANSACTION 命令

在 system_server 进程中的服务端 ActivityManagerService 收到 ATTACH_APPLICATION_TRANSACTION 命令后进行处理,调用 attachApplication()。

  • ActivityMangerService.attachApplication() -> attachApplicationLocked()

首先会获取到进程信息 ProcessRecord。 绑定死亡通知,移除进程启动超时消息。 获取到应用 ApplicationInfo 并绑定应用 IApplicationThread.bindApplication(appInfo)。

然后检查 App 所需组件。

Activity: 检查最顶层可见的 Activity 是否等待在该进程中运行,调用 ActivityStackSupervisor.attachApplicationLocked()。

Service:寻找所有需要在该进程中运行的服务,调用 ActiveServices.attachApplicationLocked()。

Broadcast:检查是否在这个进程中有下一个广播接收者,调用 sendPendingBroadcastsLocked()。

此处讨论 Activity 的启动过程,只讨论 ActivityStackSupervisor.attachApplicationLocked() 方法。

5. 调用 realStartActivityLocked()

  • ActivityStackSupervisor.attachApplicationLocked() -> realStartActivityLocked()

将该进程设置为前台进程 PROCESS_STATE_TOP,调用 ApplicationThreadProxy.scheduleLaunchActivity()。

  • ApplicationThreadProxy.scheduleLaunchActivity()

发送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令

6. 发送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令

发送送完 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,还会发送 BIND_APPLICATION_TRANSACTION 命令来创建 Application。

  • ApplicationThreadProxy.bindApplication()

发送 BIND_APPLICATION_TRANSACTION 命令

BIND_APPLICATION_TRANSACTION 命令处理

在 app 进程中,收到 BIND_APPLICATION_TRANSACTION 命令后调用 ActivityThread.bindApplication()。

  • ActivityThread.bindApplication()

缓存 Service,初始化 AppBindData,发送消息 H.BIND_APPLICATION。

  • ActivityThread.handleBindApplication()

设置进程名,获取 LoadedApk 对象,创建 ContextImpl 上下文,LoadedApk.makeApplication() 创建 Application 对象,调用 Application.onCreate() 回调方法。

SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令处理

app 进程中,收到 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令后调用 ApplicationThread.scheduleLaunchActivity()。

  • ApplicationThread.scheduleLaunchActivity()

发送消息 H.LAUNCH_ACTIVITY。

7. 发送消息 H.LAUNCH_ACTIVITY

  • ActivityThread.handleLaunchActivity()

最终回调目标 Activity 的 onConfigurationChanged(),初始化 WindowManagerService。

  • ActivityThread.performLaunchActivity()

检查 Application 是否创建,最终回调目标 Activity 的 onCreate()。

8. 调用 handleResumeActivity()

  • ActivityThread.handleResumeActivity()

最终回调目标 Activity 的 onStart(),onResume()。

Activity 启动过程中涉及到的类

frameworks/base/services/core/java/com/android/server/am/  - ActivityManagerService.java  - ActivityStackSupervisor.java  - ActivityStack.java  - ActivityRecord.java  - ProcessRecord.javaframeworks/base/core/java/android/app/  - IActivityManager.java  - ActivityManagerNative.java (内含 AMP)  - ActivityManager.java  - IApplicationThread.java  - ApplicationThreadNative.java (内含 ATP)  - ActivityThread.java (内含 ApplicationThread)  - ContextImpl.java

总结

Activity 的启动流程已经分析完了,相对于 Binder 机制来说是不是很简单。 这里只是从大体逻辑分析了一遍 Activity 的启动过程,简单了解下 Activity 启动时都经历了什么,想要深入的了解实现细节还是需要看一下 Android 的源码。

参考资料

  • startActivity启动过程分析
  • Android应用程序的Activity启动过程简要介绍和学习计划
  • 《深入理解 Android 内核设计思想》

更多文章

https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode