singleTask 清栈过程中 Activity 销毁与目标 Activity 恢复的时序分析

1. 启动 App 的流程

大致分为两类:冷启动和热启动。

冷启动:App 生命周期已结束,被重新拉起。

热启动:App 生命周期存活,可能处于后台,被重新拉起到前台。

示例:以从 Launcher 应用池点开一个 App 为例,经历几个节点:

  1. Launcher 进程发出建立 App 的请求。
  2. System_server 中的 ActivityService 处理传进来的创建 App 的请求,在这里有个判断逻辑,判断此 App 是热启动还是冷启动。
  3. 如果是冷启动,先走 zygote 创建 App 进程;如果是热启动,直接进入第 4 步。
  4. 进入到 App 进程。

这里可以参考链接:Android应用启动流程一次看透_android startinstrumentation-CSDN博客

2. Android 的窗口构成

已知大概组成结构如下,连接设备后执行 dumpsys activity 取一段日志如下:

3. 举例一个场景

我创建了几个 Activity:MainActivity(standard)、HomeActivity(singleTask)、CarDetectActivity(standard)。其中mainactivity有个业务流程,在create的时候会自动拉起homeactivity。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".CarDetectActivity"
            android:exported="false"
            android:theme="@style/Theme.MyApplication" />

        <activity
            android:name=".HomeActivity"
            android:exported="false"
            android:launchMode="singleTask"
            android:theme="@style/Theme.MyApplication" />

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.MyApplication">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

首先我通过依次打开 MainActivity → HomeActivity → CarDetectActivity。

Task 中的 ActivityRecord 记录如下:

3.1 通过命令行:重新启动 MainActivity,这个 flag 是将 Task 中已有的 Activity 复用到栈顶

复制代码
am start -n com.example.myapplication/.MainActivity -f 0x00020000

。

此时再执行 dumpsys activity 信息如下:可以看到 MainActivity 被移动到了栈顶,且里面的记录号没变。

3.2 通过命令行启动页面,不带flag的方式

am start -n com.example.myapplication/.MainActivity

通过命令行 dumpsys activity | grep -A 20 "Task display areas" 查看,此时是没有复用的。

栈内信息从:

变成了:

这是由于在该task中新建了 MainActivity,而 MainActivity 是重新 create 的。create 中有 HomeActivity 的流程,这里 resume 原来的 HomeActivity。而 HomeActivity 的 launchMode 是 singleTask,然后 HomeActivity 需要把它上面的 Activity 都清理掉,也就是把新建的 MainActivity 和上面的 CarDetectActivity 都销毁掉。

可以看见下面的日志是符合逻辑的:首先创建一个 MainActivity,然后 HomeActivity 被 restart 复用。它上面的 CarDetectActivity 被 destroy,刚才新建的 MainActivity 生命周期也 destroy。

日志如下:

结论:

  • Activity启动不是创建Activity,而是一次Task/Activity匹配过程
  • ActivityRecord是否复用由flag和launchMode共同决定
  • singleTask最大的影响不是复用,而是清理栈
  • Task的baseIntent决定Task身份,会影响后续启动匹配
  • 看到Activity生命周期异常,要先分析Task栈变化,而不是只看Activity代码
相关推荐
好的佩奇8 小时前
蓝牙之通信架构
android·flutter·蓝牙
FlightYe8 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
诸神黄昏EX9 小时前
Android fw BatteryService
android
alexhilton9 小时前
提升 Android Compose 页面的流畅度
android·kotlin·android jetpack
撩得Android一次心动11 小时前
Android中Gradle网络下载超时、更改存放位置(解决方案)
android·gradle
HQL_seven12 小时前
【Activity】Android Activity详解
android
AI2中文网12 小时前
安卓 15/16 手机软键盘遮挡输入框、布局顶不上去?已解决:重新编译即可
android·智能手机
字节暗面12 小时前
Android APP 加固横评记录:爱加密、梆梆、网易易盾与腾讯 ACE
android·逆向工程·加固
落魄Android在线炒饭13 小时前
Android 实战问题反推 OpenGL 概念(上)
android·opengl
booboosui13 小时前
DeepSeek 的 Worker 调得动 GitHub,调不动微信:三类 Worker 的实现差别
android