Android 第5种启动模式:singleInstancePerTask
随着 Android 版本的更新,应用启动模式逐渐丰富。在 Android 12 中,新增了一种启动模式——singleInstancePerTask
。它是继 standard
、singleTop
、singleTask
和 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:
- MainActivity:标准启动模式
standard
。 - SingleInstancePerTaskActivity:
singleInstancePerTask
启动模式。 - 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
,它在任务栈管理上提供了更高的自由度。