Android 面试| Activity的创建启动流程
一. 概述
startActivity
的整体流程与startService启动过程分析非常相近,但比Service启动更为复杂,多了stack/task以及UI的相关内容以及Activity的生命周期更为丰富。Activity启动发起后,通过Binder最终交由system进程中的AMS来完成。
在开始解释之前,先说一下ActivityRecord和ActivityStack是两个非常重要的概念,它们是系统管理Activity生命周期和状态的关键数据结构。下面简要介绍这两个概念:
ActivityRecord
ActivityRecord是Android系统中用于表示每个Activity的一个数据结构。它包含了Activity的所有信息和状态,例如:
- Activity的类名:Activity的Java类,用于系统创建实例。
- Intent:启动Activity时传递的Intent对象,包含了启动Activity的目的和传递的数据。
- 任务栈(TaskRecord)的引用:Activity所属的任务栈,表示Activity在多任务视图中的位置。
- 窗口令牌(Window Token):用于与WindowManager通信,创建和管理Activity的窗口。
- 生命周期状态:记录Activity当前所处的生命周期状态,如运行(RESUMED)、暂停(PAUSED)、停止(STOPPED)等。
- 配置更改信息:Activity在配置更改(如屏幕旋转)时的状态和数据。
ActivityRecord是ActivityManagerService(AMS)用来跟踪和管理Activity的主要数据载体。当一个新的Activity被启动时,系统会查找是否存在对应的ActivityRecord,如果不存在,则创建一个新的ActivityRecord,并将其与Activity实例关联。
ActivityStack
ActivityStack是Android系统中用于管理一组Activity的数据结构,它代表了Activity的栈式结构。每个ActivityStack包含了一系列的ActivityRecord,这些Activity按照它们被创建的顺序排列,后进先出(LIFO)的原则进行管理。
- 栈顶(Top Activity):当前正在与用户交互的Activity位于栈顶。
- 栈内其他Activity:其他Activity按照它们被启动的顺序依次存放在栈中。
- 任务栈(Task):一个ActivityStack可以代表一个任务,任务是一组Activity的集合,用户可以在多任务视图中切换不同的任务。
ActivityStack允许系统有效地管理Activity的生命周期和状态,支持Activity之间的切换、返回操作以及配置更改时的状态恢复。当用户离开当前Activity时,系统会将其下推到ActivityStack中,而新的Activity则被放置在栈顶。当用户返回时,系统会将Activity从栈顶弹出,并恢复其之前的状态。
通过ActivityRecord和ActivityStack,Android系统能够灵活地管理多个Activity及其状态,提供流畅的多任务操作体验。
Activity启动流程
好,了解完了两个Activity在启动流程中比较重要的概念以后,我们再开始看Activity的启动流程,下面我以伪代码的形式解释启动的过程和几个关键方法:
// 初始化:系统启动时,ActivityManagerService(AMS) 会被启动并初始化
function main() {
// 1. 用户点击应用图标或者系统需要启动Activity时,调用startActivity()方法
intent = createIntent(activityName, action, dataUri, ...);
options = createActivityOptions(if any);
resultCode = -1; // 默认没有结果码
resultData = null; // 默认没有结果数据
startActivity(intent, options, resultCode, resultData);
}
// 2. AMS接收到startActivity请求后,根据Intent找到对应的ActivityRecord,并进行调度
function startActivity(intent, options, resultCode, resultData) {
ActivityRecord = findActivityRecord(intent);
if (ActivityRecord == null) {
// 如果ActivityRecord不存在,需要创建新的ActivityStack
activityStack = createNewActivityStack();
ActivityRecord = createActivityRecord(intent, activityStack);
}
// 3. AMS将ActivityRecord添加到ActivityStack中,并开始启动流程
addActivityToStack(ActivityRecord, activityStack);
startActivityInStack(ActivityRecord, options);
// 4. AMS通知WindowManagerService(WMS)创建Activity的窗口
window = createWindowForActivity(ActivityRecord);
WindowManagerService.addWindow(window);
// 5. AMS将Activity的状态更新为RESUMED,表示Activity已经准备好并可以与用户交互
updateActivityState(ActivityRecord, STATE_RESUMED);
}
// 6. ActivityThread在收到startActivity请求后,通过Binder调用Activity的onCreate()等生命周期方法
function onCreate(ActivityRecord) {
// 初始化Activity的成员变量,设置布局等
setupActivity();
// 调用Activity的onStart()方法,Activity进入STARTED状态
onStart(ActivityRecord);
// 最后调用Activity的onResume()方法,Activity进入RESUMED状态,可以与用户交互
onResume(ActivityRecord);
}
// 7. 用户与Activity交互结束后,可以选择调用finish()方法结束Activity
function finish() {
// 调用Activity的onPause()方法,Activity从RESUMED状态变为PAUSED状态
onPause(ActivityRecord);
// 移除Activity窗口
removeWindow(WindowManagerService.getWindowForActivity(ActivityRecord));
// 更新Activity状态为FINISHED
updateActivityState(ActivityRecord, STATE_FINISHED);
// 如果有设置结果码或数据,通过结果Intent返回给调用者
if (resultCode != -1 || resultData != null) {
sendResult(resultCode, resultData);
}
// 从ActivityStack中移除ActivityRecord
removeActivityFromStack(ActivityRecord);
}
// 8. 如果Activity被系统销毁,会调用onDestroy()方法
function onDestroy(ActivityRecord) {
// 清理资源,如关闭数据库连接,停止动画等
cleanUpResources();
}
启动流程:
- 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
- system_server进程接收到请求后,向zygote进程发送创建进程的请求;
- Zygote进程fork出新的子进程,即App进程;
- App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
- system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
- App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
- 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面
Launch Mode
这里展开简单说说ActivityInfo.java中定义了4类Launch Mode:
LAUNCH_MULTIPLE(standard
):每次启动新Activity,都会创建新的Activity,这是最常见标准情形;
LAUNCH_SINGLE_TOP(SingleTop
): 当启动新Acitity,在栈顶存在相同Activity,则不会创建新Activity;其余情况同上;比较常见的场景就是给前台通知跳转的Activity
设置,因为你肯定不会想前台Activity
已经是该Activity
的情况下,点击通知,又给你再创建一个同样的Activity
。
LAUNCH_SINGLE_TASK(SingleTask
):当启动新Acitity,在栈中存在相同Activity(可以是不在栈顶),则不会创建新Activity,而是移除该Activity之上的所有Activity;其余情况同上;常见于跳转到主界面。
LAUNCH_SINGLE_INSTANCE(SingleInstance
):每个Task栈只有一个Activity,其余情况同上。常见于初始化界面,预览页;
再来说说几个常见的Intent flag含义:
- FLAG_ACTIVITY_NEW_TASK:将Activity放入一个新启动的Task;
- FLAG_ACTIVITY_CLEAR_TASK:启动Activity时,将目标Activity关联的Task清除,再启动新Task,将该Activity放入该Task。该flags跟FLAG_ACTIVITY_NEW_TASK配合使用。
- FLAG_ACTIVITY_CLEAR_TOP:启动非栈顶Activity时,先清除该Activity之上的Activity。例如Task已有A、B、C3个Activity,启动A,则清除B,C。类似于SingleTop。
//源码剖析, 分析android Activity启动流程,相关源码:
frameworks/base/services/core/java/com/android/server/am/
- ActivityManagerService.java
- ActivityStackSupervisor.java
- ActivityStack.java
- ActivityRecord.java
- ProcessRecord.java
frameworks/base/core/java/android/app/
- IActivityManager.java
- ActivityManagerNative.java (内含AMP)
- ActivityManager.java
- IApplicationThread.java
- ApplicationThreadNative.java (内含ATP)
- ActivityThread.java (内含ApplicationThread)
- ContextImpl.java
启动Activity较为复杂,后续计划再进一步讲解生命周期过程与系统是如何交互,以及UI渲染过程,敬请期待。
以后每两天之内更新一道Android常见的面试题,以自己的角度去通俗简单易懂形式去说,不深入源码但讲基本原理,以伪代码为核心;如果你比较想问什么问题,可以评论。
转载自:https://juejin.cn/post/7352555787301060642