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代码
相关推荐
峥嵘life14 小时前
Android WiFi连接过程 wpa_supplicant 日志分析
android·开发语言·php
Android小码家15 小时前
OWASP 移动应用安全之授权(MASTG-DEMO-0090)
android·安全·frida
Summer-Bright15 小时前
消费者 AI 变现竞争:从“一家独大“到“iOS vs Android“,谁在为 AI 买单?
android·人工智能·ios·ai·自然语言处理·agi
Xzaveir16 小时前
企业号码资产平台:逐号状态、事件日志与批次聚合
android·人工智能
恋猫de小郭17 小时前
Flutter 3D 渲染的全新选择和应用场景
android·前端·flutter
—Miss. Z—17 小时前
计算机二级MySQL——简单应用题(事件&视图)
android·mysql·adb
邪修king18 小时前
C++ 进阶终章:异常机制与智能指针全解 —— 从错误处理到 RAII 资源管理,打通现代 C++ 的核心命脉
android·数据结构·c++
三少爷的鞋18 小时前
LiveData 的缺陷:为什么我现在越来越少使用 LiveData?
android
雨白1 天前
NDK 初探:基于 C++ 实现参数哈希与签名校验
android
程序员正茂1 天前
Android studio中初步使用OpenCV库
android·opencv