likes
comments
collection
share

Android 面试| Activity的创建启动流程

作者站长头像
站长
· 阅读数 6

一. 概述

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();
}

Android 面试| Activity的创建启动流程 启动流程:

  1. 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求;
  3. Zygote进程fork出新的子进程,即App进程;
  4. App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
  7. 主线程在收到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常见的面试题,以自己的角度去通俗简单易懂形式去说,不深入源码但讲基本原理,以伪代码为核心;如果你比较想问什么问题,可以评论。