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代码
相关推荐
geovindu18 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
知之则吱吱20 小时前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
墨天梦21 小时前
D09_Retrofit接口与数据转换
android·kotlin·retrofit
电商API_180079052471 天前
闲鱼商品列表API接口商品详情API接口请求示例(含一份真实响应数据示例)
android·数据挖掘·网络爬虫·跨境电商·反向海淘
我命由我123451 天前
Android 广播 - 组件通信
android·java·开发语言·android studio·android jetpack·android-studio·android runtime
阿俊-全栈开发1 天前
LikeShop 单商户标准版商品管理二开:分类、SKU 规格与库存联动实现
android·likeshop·likeshop开源商城
用户2181697049301 天前
Kotlin 语法二
android
妖星1 天前
android 源码分析surfaceFinger是如何通过设置属性启动bootanim
android
JoyMonitor1 天前
APK mmap 内存增长定位:pagemap 与 DEX 结构联合定位方法
android