startActivity()的流程

本文详细介绍了Android中startActivity()方法的内部调用流程,包括如何启动新的Activity、暂停当前Activity以及Activity之间的切换机制。此外,还展示了从用户点击图标到Activity启动的整个过程。

10.1.3  startActivity()的流程(1)

程序员可以直接调用startActivity()启动指定的Activity。前面说过,尽管从用户的角度来看,启动Activity有不同的方式,但是其主体流程是完全相同的,前端各种交互方式最后都会调用到startActivity()启动。因此,首先介绍startActivity()的流程。

1.概述

调用流程可大致归结为如图10-1和图10-2所示,由于版面限制,该图被划分为两部分。

 
图10-1  startActivity()的内部调用流程

一般调用startActivity()方法是从用户单击桌面图标开始的,经过各种调用,最后导致调用startActivity()。本例假设当前正在运行A,而单击图标后会运行B。

AmS收到客户请求startActivity()后,会首先暂停当前的Activity,因此要判断mResumedActivity是否为空。在一般情况下,该值都不为空,如果不为空,AmS会通知A所在客户进程暂停,执行该Activty,并立即返回,返回后AmS就又"睡觉"去了。读者可能觉得奇怪,AmS"睡觉"去了,谁来启动B呢?这正是AmS的异步机制的好处,异步机制允许执行完一个命令后就去休息,而当远程执行完某个命令后再回调。这种方式广泛应用于Android的内核实际中,大家要迅速解除这种疑惑。

当A进程完成暂停后,报告AmS,这时AmS开始执行completePaused()。该方法中先要检查目标Activity是否在mHistory列表中,如果在,说明目标进程还在运行,目标Activity只是处于stop状态,还没有finish,所以通知B进程直接resume指定的Activity即可。如果不在mHistory列表中,则继续执行如图10-2所示的流程。

 
图10-2  startActivity()的内部调用流程(续)

检查目标Activity所在的进程是否存在,如果不存在则必须首先启动对应的进程。当对应的进程启动后,B进程会报告AmS自己已经启动,于是执行AmS的attachApplication()方法,该方法可理解为B进程请求AmS给自己安排(attach)一个具体要执行的Activity,此时AmS继续调用resumeTopActivity(),通知B进程执行指定的Activity。如果指定的HistoryRecord在B进程中不存在,则B调用handleLaunchActivity()创建一个该Activity实例;如果已经存在,则调用handleResumeActivity()恢复已有的Activity的运行。这个逻辑的意思就是说,在ActivityThread中可以存在同一个Activity的多个实例,对应了AmS中mHistory的多个HistoryRecord对象。在一般情况下,当调用startActivity(intent)的FLAG为NEW_TASK时,AmS会首先从mHistory中找到指定Activity所在的Task,然后启动Task中的最后面一个Activity;如果FLAG不为NEW_TASK,那么AmS会在当前Task中重新创建一个HistoryRecord,这就有可能创建同一个Activity的多个HistoryRecord对象,在ActivityThread端就可能创建同一个Activity类的多个实例。

2.单击图标的过程

关于startActivity()的细节过程如附图3所示,本图绘制时遵循以下规则:

假设class A的内部函数关系如下示意代码。

 
  1. public class Persedu {  
  2.     void f1(){  
  3.         f2();  
  4.     }  
  5.       
  6.     void f2(){  
  7.         f3();  
  8.     }  
  9.       
  10.     void f3(){  
  11.         x1();  
  12.         x2();  
  13.         x3();  
  14.     }  
  15.       
  16.     void x1(){};  
  17.     void x2(){};  
  18.     void x3(){};  
  19. }  
### Android `startActivity` 方法的源码解析与流程详解 #### 调用入口 当开发者通过 `context.startActivity(intent)` 或者 `startActivityForResult(intent, requestCode)` 来启动一个新的 Activity 时,实际上触发了一系列复杂的系统级操作。这些操作可以分为多个阶段,涉及到了框架层和底层系统的交互。 --- #### 主要流程概述 在调用 `startActivity()` 方法之后,Android 系统会执行以下核心步骤: 1. **Intent 对象传递** - 开发者构建了一个 `Intent` 对象并将其作为参数传入到 `startActivity()` 中[^3]。 - 这个 `Intent` 定义了目标组件以及可能携带的数据或标志位。 2. **AMS (ActivityManagerService) 的介入** - 在应用进程中,`ContextImpl` 类中的 `startActivity()` 方法会被调用,并进一步封装成一个异步请求发送给 AMS[^1]。 - 此过程中,可能会经过权限校验、任务栈管理等一系列逻辑判断。 3. **Binder IPC 通信机制** - 应用程序进程通过 Binder 机制向系统服务端(即 AMS 所运行的服务端)发起跨进程调用。 - 经过多次内部转发后,最终到达 AMS 的 `startActivityAsUser()` 方法[^4]。 4. **Activity 启动决策** - AMS 需要决定如何处理这个新的 Activity 请求。如果目标 Activity 已经存在于当前的任务栈中,则可以选择复用;否则需要创建新实例。 - 如果目标 Activity 属于另一个应用程序包名下的独立进程,则还需要额外启动该进程[^2]。 5. **Zygote 孵化子进程** - 若需启动的新 Activity 不在同一进程中,则由 Zygote 使用 fork 创建一个新的 Java 虚拟机实例。 - 新进程中初始化 `ApplicationThreadProxy` 和主线程循环器 Looper,随后加载指定的应用上下文环境。 6. **绑定 Application Thread** - 在新进程中,AMS 将通过 H 键盘消息通知客户端线程去真正地完成生命周期回调工作。 - 实际上是通过调用 `ActivityClientRecord.performLaunchActivity()` 函数来逐步建立 UI 渲染所需的资源对象树结构。 7. **onCreate/onResume 生命周期触发** - 最终,在一切准备就绪的情况下,目标 Activity 的标准生命周期方法依次被激活,从而呈现出完整的界面效果。 --- #### 关键代码片段展示 以下是部分重要环节对应的伪代码表示形式: ```java // ContextImpl.java 中定义的方法 public void startActivity(Intent intent) { Instrumentation instr = getInstrumentation(); if (instr != null) { instr.callActivityOnStart(this); } // 发送至 AMS 处理... } // ActivityManagerService.java 内部实现细节简化版 private final boolean startActivityLocked(IApplicationThread caller, String callingPackage, Intent intent,...){ ... mActivityStarter.execute(); } ``` 对于特定场景下涉及到远程进程唤醒的部分如下所示: ```java Process.ProcessStartResult startResult = Process.start( "android.app.ActivityThread", app.processName, uid, gid, gids, debugFlags, app.info.targetSdkVersion, mountExternal, null, null); ``` 上述过程展示了从高层 API 到低层次操作系统层面之间的紧密协作关系。 --- #### 总结说明 综上所述,整个 `startActivity` 流程不仅包含了丰富的业务规则判定,还融合了大量的性能优化策略和技术手段支持高效并发控制。理解这一系列动作有助于深入掌握 Android 平台架构设计原理及其运作规律。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值