Android Activity启动模式中 singleTask 和 singleTop 的区别

一、背景知识

在Android开发中,Activity是应用程序的核心组件之一,用于展示用户界面和处理用户交互。在Android中,每个Activity都有一个启动模式(launch mode),用于定义该Activity如何在任务栈(task stack)中启动和管理。其中,两种常见的启动模式是 singleTask 和 singleTop。本文将详细介绍这两种启动模式的区别及使用场景。

二、singleTask和singleTop的区别

1. singleTask 启动模式

singleTask启动模式表示一个Activity只能存在于一个任务栈中的栈底位置。当一个新的实例被启动时,系统会先查找是否存在该任务栈,如果存在,则将该任务栈调至前台,并移除在该Activity之上的所有其他Activity实例;如果不存在,则创建新的任务栈,并将Activity实例置于栈底。

特点:

  • 一个任务栈只能存在一个该Activity实例;
  • 如果在任务栈中已经存在该Activity实例,则会将其上方的所有Activity实例都移除;
  • 如果在任务栈中不存在该Activity实例,则会创建新的任务栈。

示意图:

gantt
    title singleTask启动模式示意图
    section 任务栈
    任务栈创建     :a1, 0, 1
    Activity1创建  :a1, 1, 2
    Activity2创建  :a2, 2, 3
    Activity3创建  :a3, 3, 4
    Activity4创建  :a4, 4, 5
    Activity5创建  :a5, 5, 6
    Activity1启动  :a1, 6, 7
    Activity2启动  :a2, 7, 8
    Activity3启动  :a3, 8, 9
    Activity4启动  :a4, 9, 10

步骤:

  1. 在AndroidManifest.xml文件中,将目标Activity的 android:launchMode 属性设置为 singleTask
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask">
    ...
</activity>
  1. 在需要启动该Activity的地方,使用 startActivity() 方法启动。
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);

2. singleTop 启动模式

singleTop启动模式表示一个Activity只能存在于一个任务栈中的栈顶位置。当一个新的实例被启动时,系统会先查找是否存在该任务栈,如果存在且栈顶是该Activity实例,则复用该Activity实例,不会创建新的实例;如果不存在该任务栈或栈顶不是该Activity实例,则创建新的任务栈并创建Activity实例。

特点:

  • 一个任务栈只能存在一个该Activity实例,并且该实例位于栈顶;
  • 如果在任务栈中已经存在该Activity实例但不在栈顶,系统会创建新的实例并将其置于栈顶。

示意图:

gantt
    title singleTop启动模式示意图
    section 任务栈
    任务栈创建     :a1, 0, 1
    Activity1创建  :a1, 1, 2
    Activity2创建  :a2, 2, 3
    Activity3创建  :a3, 3, 4
    Activity4创建  :a4, 4, 5
    Activity5创建  :a5, 5, 6
    Activity1启动  :a1, 6, 7
    Activity2启动  :a2, 7, 8
    Activity3启动  :a3, 8, 9
    Activity1启动  :a1, 9, 10
    Activity4启动  :a4, 10, 11

步骤:

  1. 在AndroidManifest.xml文件中,将目标Activity的 android:launchMode 属性设置为 singleTop
<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">
    ...
</activity>
  1. 在需要启动该Activity的地方,使用 startActivity() 方法启