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代码
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui