Android Activity启动流程详解

news2025/5/12 14:57:37

目录

Activity 启动流程详细解析

1. 应用层发起启动请求

1.1 调用 startActivity()

1.2 通过 Instrumentation 转发请求

2. 系统服务处理(AMS 阶段)

2.1 Binder IPC 通信

2.2 AMS 处理流程

2.3 跨进程回调 ApplicationThread

3. 目标进程初始化(ActivityThread 阶段)

3.1 进程创建(Zygote Fork)

3.2 初始化 ActivityThread

3.3 创建 Application 对象

4. 目标 Activity 的创建与生命周期

4.1 处理 AMS 的启动请求

4.2 创建 Activity 实例

4.3 生命周期回调

5. 界面渲染(WindowManager 与 View 系统)

5.1 视图树构建

5.2 视图测量、布局、绘制

5.3 同步到屏幕

6. 流程图解

7. 关键机制深度解析

7.1 Binder IPC 在启动流程中的作用

7.2 启动模式(LaunchMode)的影响

7.3 性能优化点

8. 总结


Activity 启动流程详细解析

Activity 的启动流程是 Android 系统中涉及多个组件协作的核心机制,从用户调用 startActivity() 到目标 Activity 完成界面渲染,整个过程分为 应用层请求、系统服务处理、进程管理、界面渲染 四个阶段,涉及 Binder IPC、AMS、Zygote、ActivityThread、WindowManager 等关键组件。以下是分步骤详细解析:


1. 应用层发起启动请求

1.1 调用 startActivity()
  • 入口:通过 Activity.startActivity(Intent) 或 Context.startActivity(Intent) 发起请求。

  • Intent 参数

    Intent intent = new Intent(this, TargetActivity.class);
    startActivity(intent);
  • 关键操作

    • Intent 封装目标 Activity 的类名、包名、启动模式(launchMode)等信息。

    • 调用 Instrumentation.execStartActivity()(实际执行启动逻辑)。

1.2 通过 Instrumentation 转发请求
  • 跨进程通信入口

    // Activity.java
    Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
        this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
  • 作用Instrumentation 是系统监控应用与组件交互的“钩子”,负责将启动请求通过 Binder 传递给 AMS


2. 系统服务处理(AMS 阶段)

2.1 Binder IPC 通信
  • 客户端:应用进程通过 ActivityManagerProxy(AMS 的 Binder 代理对象)发送请求。

  • 服务端:请求到达 ActivityManagerService(AMS),执行 startActivity() 核心逻辑。

2.2 AMS 处理流程
  • 步骤

    1. 权限验证:检查调用方是否有权限启动目标 Activity。

    2. 解析 Intent

      • 根据 Intent 中的 ComponentName 解析目标 Activity 信息。

      • 若未显式指定类名,通过 PackageManagerService 匹配隐式 Intent。

    3. 任务栈(Task Stack)管理

      • 根据目标 Activity 的 launchMode(如 standardsingleTop)决定是否复用现有实例或创建新任务栈。

      • 例如:singleTask 会清除目标 Activity 上方的其他 Activity。

    4. 进程检查

      • 若目标 Activity 所属应用进程未启动,触发 Zygote 创建新进程。

      • 若进程已存在,直接复用。

2.3 跨进程回调 ApplicationThread
  • Binder 回调:AMS 通过 IApplicationThread 接口(ActivityThread 的内部类)通知应用进程处理后续逻辑。

  • 关键代码

    // AMS 通过 Binder 调用应用进程的 ApplicationThread.scheduleLaunchActivity()
    app.thread.scheduleLaunchActivity(intent, ...);

3. 目标进程初始化(ActivityThread 阶段)

3.1 进程创建(Zygote Fork)
  • 触发条件:若目标应用进程未启动,AMS 通过 Zygote 进程 fork 新进程。

  • 流程

    1. AMS 向 Zygote 发送 socket 请求。

    2. Zygote 复制自身进程,生成新进程。

    3. 新进程执行 ActivityThread.main() 入口方法。

3.2 初始化 ActivityThread
  • 主线程初始化

    // ActivityThread.java
    public static void main(String[] args) {
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false); // 绑定到 AMS
        Looper.loop();
    }
  • 绑定 AMSActivityThread.attach() 通过 Binder 向 AMS 注册应用进程。

3.3 创建 Application 对象
  • 触发:AMS 回调 bindApplication()

  • 流程

    1. 加载 Application 类(通过 ClassLoader)。

    2. 实例化 Application 并调用 onCreate()

    3. 初始化 ContentProvider(按优先级顺序)。


4. 目标 Activity 的创建与生命周期

4.1 处理 AMS 的启动请求
  • 回调入口ApplicationThread.scheduleLaunchActivity()

  • 封装参数:将 AMS 传递的数据封装为 ActivityClientRecord

  • 发送消息:通过 Handler 将启动请求发送到主线程消息队列。

4.2 创建 Activity 实例
  • 反射创建实例

    // ActivityThread.java
    java.lang.ClassLoader cl = appContext.getClassLoader();
    Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), intent);
  • 关键对象

    • ContextImpl:Activity 的上下文环境,持有 ResourcesPackageInfo 等。

    • Window:每个 Activity 关联一个 PhoneWindow 对象。

4.3 生命周期回调
  • 顺序调用

    1. onCreate():初始化界面(setContentView())。

    2. onStart():Activity 可见但未聚焦。

    3. onResume():Activity 进入前台并获取焦点。

  • 触发界面渲染onResume() 完成后,WindowManager 将 DecorView 添加到屏幕。


5. 界面渲染(WindowManager 与 View 系统)

5.1 视图树构建
  • setContentView()

    // Activity.java
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
    • PhoneWindow 创建 DecorView 并加载布局文件。

5.2 视图测量、布局、绘制
  • ViewRootImpl:管理视图树的三大流程:

    1. measure():计算 View 的尺寸。

    2. layout():确定 View 的位置。

    3. draw():将 View 绘制到屏幕上。

5.3 同步到屏幕

  • WindowManager.addView()

    // WindowManagerGlobal.java
    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
    root.setView(view, wparams, panelParentView);
    • ViewRootImpl 通过 Choreographer 监听垂直同步信号(VSync),触发界面刷新。


6. 流程图解

用户调用 startActivity()
        │
        ↓
Instrumentation.execStartActivity()
        │
        ↓ (Binder IPC)
AMS.startActivity()
        │
        ↓
AMS 解析 Intent、检查权限、管理任务栈
        │
        ↓
目标进程是否存在? ── 否 → Zygote fork 新进程
        │
        ↓
AMS 通过 ApplicationThread 回调目标进程
        │
        ↓ (Handler 消息机制)
ActivityThread.handleLaunchActivity()
        │
        ↓
创建 Activity 实例 → onCreate() → onStart() → onResume()
        │
        ↓
WindowManager 添加 DecorView
        │
        ↓
ViewRootImpl 触发 measure/layout/draw
        │
        ↓
界面显示到屏幕


7. 关键机制深度解析

7.1 Binder IPC 在启动流程中的作用
  • 客户端:应用进程通过 ActivityManagerProxy 发送请求。

  • 服务端:AMS 运行在 system_server 进程,通过 Binder 线程池处理请求。

  • 跨进程回调:AMS 通过 IApplicationThread 接口回调应用进程。

7.2 启动模式(LaunchMode)的影响
  • standard:默认模式,每次启动新实例。

  • singleTop:栈顶复用,触发 onNewIntent()

  • singleTask:栈内复用,清除上方 Activity。

  • singleInstance:独占任务栈,全局唯一实例。

7.3 性能优化点
  • 冷启动优化:减少 Application.onCreate() 和首屏 Activity 的初始化耗时。

  • 延迟加载:将非关键操作移至 onResume() 之后或子线程。

  • 主题预加载:使用 windowBackground 避免白屏。


8. 总结

Activity 的启动流程是 Android 系统设计的核心体现,涵盖 IPC 通信、进程管理、组件生命周期、界面渲染 等多个维度。理解此流程有助于:

  • 性能调优:定位启动耗时瓶颈。

  • 问题排查:分析 ANR、界面卡顿等问题的根因。

  • 系统定制:修改 AMS 或 ActivityThread 逻辑实现特殊需求(如插件化、多任务管理)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2308648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

夜天之书 #106 Apache 软件基金会如何投票选举?

近期若干开源组织进行换届选举。在此期间,拥有投票权的成员往往会热烈讨论,提名新成员候选人和治理团队的候选人。虽然讨论是容易进行的,但是实际的投票流程和运作方式,在一个成员众多的组织中,可能会有不少成员并不清…

保姆级教程:用Chart.js实现柱状图与折线图联动

保姆级教程:用Chart.js实现柱状图与折线图联动 ▲ 最终实现的交互式组合图表效果 一、技术原理剖析 1.1 Chart.js渲染机制 Chart.js基于HTML5 Canvas实现图表绘制,其核心原理包括: 数据绑定:将数据对象映射为图形元素分层渲染:通过order属性控制图层叠加顺序坐标系计算:…

初阶MySQL(两万字全面解析)

文章目录 1.初识MySQL1.1数据库1.2查看数据库1.3创建数据库1.4字符集编码和排序规则1.5修改数据库1.6删除数据库 2.MySQL常用数据类型和表的操作2.(一)常用数据类型1.数值类2.字符串类型3.二进制类型4.日期类型 2.(二)表的操作1查看指定库中所有表2.创建表 3.查看表结构和查看表…

4.3MISC流量分析练习-wireshark-https

流量分析题目的例题 1.了解wireshark的过滤方式 2.了解tls跟ssl协议基本还原 3.了解xor基本变换方式,获取flag 附件是一个流量包,打开之后有各种流量,但是分析无果,然后丢到kali中使用binwalk进行分析,发现有一个r…

STM32CubeMx DRV8833驱动

一、DRV8833驱动原理 ​ STBY口接单片机的IO口,STBY置0电机全部停止,置1才能工作。STBY置1后通过AIN1、AIN2、BIN1、BIN2 来控制正反转。 AIN1AIN2电机状态00停止1speed反转speed1正转11停止 其中A端(AIN1与AIN2)只能控制AO1与…

【Qt】ffmpeg照片提取、视频播放▲

目录 一、图像的成像原理: RGB成像原理: YUV成像原理: 二、多线程 三、ffmpeg解码(照片提取) 1.准备工作 (1)在工程文件夹里面新建三个文件夹 (2)在main函数中加…

Vue+Elementui 全局配置el-table表格列宽可拖拽

1、需求分析 如何让表格列宽可以拖动 elementui的el-table如果想要列宽可以拖动的话 有一个属性叫 border 在模板里添加这个属性即可实现 但是系统里面的表格我不可能一个一个去添加border太麻烦 如果能够全局配置岂不是非常省时间吗 我们在main.js里面通过全局混入的方式来…

SQL命令详解之增删改数据

目录 简介 1 添加数据 1.1 基础语法 1.2 SQL 练习 2 修改数据 2.1 基础语法 2.2 SQL 练习 ​3 删除数据 3.1 基础语法 3.2 SQL 练习 总结 简介 在数据库操作中,增、删、改是最基础的操作,它们通常对应着SQL中的INSERT、DELETE和UPDATE命令。…

鸿蒙开发第4篇__关于在鸿蒙应用中使用Java语言进行设计

本博文对于鸿蒙APP程序员来说,很重要 HarmonyOS从 API8 开始不再支持使用Java作为开发语言,未来的新功能将在ArkTS中实现. API 8对应的是HarmonyOS 3.0.0版本, 2022年7月27日, 华为发布了HarmonyOS 3.0。 请看下图: 因此&#…

Linux三种网络方式

前言 发现运维啥都得会,这周就遇到了网络问题自己无法解决,因此痛定思痛学一下。 参考文献 你管这破玩意叫网络? 桥接模式、NAT模式、仅主机模式,原来是这样工作的 交换机 构成局域网,实现所有设备之间的通信。 …

Spring DIIoC

一.IoC 1.简介 什么是IoC?IoC,全称 Inversion of Control,控制反转。IoC是Spring的核心思想,Spring是⼀个“控制反转”的容器。 如果我们需要一个对象,正常来说我们是通过new一个对象,这个时候我们依赖的…

【前端基础】Day 2 CSS层叠样式表

目录 1.CSS简历 2.CSS 基础选择器 2.1标签选择器 2.2类选择器 2.3 id选择器 2.4通配符选择器 2.5总结 3.CSS字体属性 字体属性总结 4.CSS文本属性 4.1颜色 4.2对齐文本 4.3装饰文本 4.4文本缩进 4.5行间距 4.6文本属性总结 5.CSS的引入方式 5.1内部样式表 …

计算机毕业设计SpringBoot+Vue.js汽车资讯网站(源码+文档+PPT+讲解)

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

nuxt常用组件库html-validator、@nuxtjs/i18n、@nuxt/image、@unocss/nuxt使用解析

html-validator 主要用于自动验证nuxt服务器呈现的HTML(SSR和SSG),以检测可能导致水合错误的HTML常见问题,有助于减少水合错误,检测常见的可访问性错误。 安装 npx nuxilatest module add html-validator配置 若自动更新nuxt.config.ts配置文…

Leetcode-最大矩形(单调栈)

一、题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 输入:matrix [["1","0","1","0","0"],["1","0&…

Vue核心知识:动态路由实现完整方案

在Vue中实现动态路由,并结合后端接口和数据库表设计,是一个复杂的项目,需要多个技术栈和步骤的配合。以下将详细描述整个实现过程,包括数据库设计、后端接口设计、前端路由配置以及如何实现动态路由的功能。 目录 一、需求分析二…

【Docker】使用Docker搭建-MySQL数据库服务

零、更换Docker镜像源 因为国内现在封锁了Docker默认拉取镜像的站点(DockerHub),而且国内大部分Docker镜像站已全部下线,导致现在很多朋友在拉取镜像的时候会出现无法拉取的现象,这时候就需要进行更换Docker镜像源。 可…

DHCP配置和地址

DHCP:动态主机配置协议 DHCP系统组成 DHCP报文结构 DHCP报文类型 DHCP工作流程 DHCP租期更新 DHCP重绑定 自动保留IP 租期设置建议 IP地址释放 DHCP地址池 DHCP配置 DHCP接口地址池配置 DHCP全局地址池配置

基于trl复现DeepSeek-R1的GRPO训练过程

1. 引入 huggingface开发了强化学习训练Transformer的库trl(参考3),借助这个trl,可以用来做GRPO的强化学习训练。魔搭ModelScope社区的文章(参考2)给出了基于Qwen基座模型Qwen2.5-0.5B-Instruct&#xff0…

常用的 pip 命令

pip 是 Python 的包管理工具,可用于安装、卸载、更新和管理 Python 包。以下是一些常用的 pip 命令: 1. 安装包 安装最新版本的包 pip install package_namepackage_name 是你要安装的 Python 包的名称,例如 pip install requests 可以安装…