Android 第5种启动模式:singleInstancePerTask

科技   2024-10-15 08:18   浙江  

Android 第5种启动模式:singleInstancePerTask

随着 Android 版本的更新,应用启动模式逐渐丰富。在 Android 12 中,新增了一种启动模式——singleInstancePerTask。它是继 standardsingleTopsingleTask 和 singleInstance 之后的第五种启动模式。本文将详细介绍 singleInstancePerTask 的工作原理、使用场景以及与其他启动模式的区别。

一、什么是 singleInstancePerTask?

singleInstancePerTask 允许一个 Activity 作为任务栈的根 Activity 来运行,并且它只会在这个任务栈中有一个实例。不过,与 singleTask 不同的是,singleInstancePerTask 可以在不同的任务栈中创建多个实例。如果启动该 Activity 时设置了 FLAG_ACTIVITY_MULTIPLE_TASK 或 FLAG_ACTIVITY_NEW_DOCUMENT 标志,那么每次启动时都会创建新的任务栈。

在 Android SDK 中,singleInstancePerTask 的定义如下:

<!-- Activity can only be running as the root activity of the task, and therefore
     there will only be one instance of this activity in a task. However, unlike
     singleTask, this activity can be started in multiple instances in different tasks. -->

<enum name="singleInstancePerTask" value="4" />

通过此定义可以看出,singleInstancePerTask 可以避免在同一个任务栈中创建多个实例,但允许在不同的任务栈中有多个实例。而 singleTask 则会限制该 Activity 只存在于一个任务栈中。

二、singleInstancePerTask 的使用场景

为了更好地理解 singleInstancePerTask,我们可以通过实际测试来查看任务栈的状态。假设我们有如下的几个 Activity:

  1. 1. MainActivity:标准启动模式 standard

  2. 2. SingleInstancePerTaskActivitysingleInstancePerTask 启动模式。

  3. 3. StandardActivity:标准启动模式 standard

示例一:MainActivity 启动 SingleInstancePerTaskActivity

当 MainActivity 启动 SingleInstancePerTaskActivity 后,可以通过 adb shell dumpsys activity activities | grep <package_name> 查看任务栈状态。输出如下:

Task{e1d436a #18 type=standard A=10147:com.example.app U=0 visible=false sz=1}
* ActivityRecord{35a6661 u0 com.example.app/.MainActivity t18}
Task{81c692c #19 type=standard A=10147:com.example.app U=0 visible=true sz=1}
* ActivityRecord{d0488df u0 com.example.app/.SingleInstancePerTaskActivity t19}

可以看到,此时有两个任务栈:MainActivity 所属的任务栈和 SingleInstancePerTaskActivity 所创建的新任务栈。

示例二:从 SingleInstancePerTaskActivity 启动 StandardActivity

接下来我们在 SingleInstancePerTaskActivity 中启动 StandardActivity,此时查看任务栈状态:

Task{81c692c #19 type=standard A=10147:com.example.app U=0 visible=true sz=2}
* ActivityRecord{455ff31 u0 com.example.app/.StandardActivity t19}
* ActivityRecord{d0488df u0 com.example.app/.SingleInstancePerTaskActivity t19}

可以看到 StandardActivity 和 SingleInstancePerTaskActivity 位于同一个任务栈中,而不会创建新的任务栈。

示例三:从 StandardActivity 再次启动 SingleInstancePerTaskActivity

这时再从 StandardActivity 启动 SingleInstancePerTaskActivity,查看任务栈状态:

Task{81c692c #19 type=standard A=10147:com.example.app U=0 visible=true sz=1}
* ActivityRecord{d0488df u0 com.example.app/.SingleInstancePerTaskActivity t19}

此时 SingleInstancePerTaskActivity 并不会重新创建,而是通过 onNewIntent() 方法复用已有实例,同时 StandardActivity 被销毁。这样的行为类似于 singleTask 的处理方式。

三、搭配 Intent.FLAG_ACTIVITY_MULTIPLE_TASK 使用

singleInstancePerTask 还可以与 Intent.FLAG_ACTIVITY_MULTIPLE_TASK 或 Intent.FLAG_ACTIVITY_NEW_DOCUMENT 配合使用,允许在不同任务栈中启动多个实例。例如,以下代码启动 SingleInstancePerTaskActivity 并创建新任务栈:

Intent intent = new Intent(this, SingleInstancePerTaskActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);

此时,任务栈的输出如下:

Task{bf82c4b #29 type=standard A=10147:com.example.app U=0 visible=true sz=1}
* ActivityRecord{ea24a0e u0 com.example.app/.SingleInstancePerTaskActivity t29}
Task{68f9c5f #28 type=standard A=10147:com.example.app U=0 visible=false sz=1}
* ActivityRecord{a528cfe u0 com.example.app/.SingleInstancePerTaskActivity t28}

可以看到,SingleInstancePerTaskActivity 的两个实例分别存在于不同的任务栈中。

四、与 singleInstance 的区别

虽然 singleInstance 和 singleInstancePerTask 都限制了 Activity 的实例数量,但它们的区别在于:

  • • singleInstance 确保整个系统中只有一个实例,并且该 Activity 独占一个任务栈。

  • • singleInstancePerTask 则允许多个任务栈中存在多个实例,但每个任务栈中只能有一个该 Activity 的实例。

五、结论

singleInstancePerTask 作为 Android 12 新增的启动模式,提供了灵活的任务栈管理方式,适用于需要在不同任务栈中复用 Activity 的场景。相较于 singleTask 和 singleInstance,它在任务栈管理上提供了更高的自由度。


虎哥Lovedroid
Android技术达人 近10年一线开发经验 关注并分享Android、Kotlin新技术,新框架 多年Android底层框架修改经验,对Framework、Server、Binder等架构有深入理解
 最新文章