安卓开发学习笔记_Activity_Activity的启动模式

  • standard
  • singleTop
  • singleTask
  • singleInstance
  • 参考


standard

  • standard是Activity默认的启动模式.
  • 在standard模式下, 每启动一个Activity, 都会在返回栈中入栈, 并处于栈顶, 系统不在乎这个Activity是否在返回栈中存在, 每次启动都会创建一个该Activity的新实例.

打开ActivityTest项目, 在FirstActivity中的onCreate()方法中添加如下代码:

// 打印实例
Log.d("FirstActivity", this.toString())
// 启动模式, 打开FirstActivity
binding.button7.setOnClickListener {
    val intent = Intent(this, FirstActivity::class.java)
    startActivity(intent)
}

生成了三个FirstActivity的实例

android 后台弹出activity权限_启动模式

singleTop

singleTop模式中, 在启动Activity时如果发现返回栈的栈顶已经是该Activity, 则认为可以直接使用它, 不会再创建新的Activity实例.

AndroidManifest.xml中修改FirstActivity的启动模式为singleTop, 代码如下:

<activity
    android:name=".FirstActivity"
    android:launchMode="singleTop"
    android:exported="true">
    ...
</activity>

多次点击按钮也只会有一个FirstActivity实例

android 后台弹出activity权限_java_02

当FirstActivity未处于栈顶时, 再启动FirstActivity还是会创建新的实例的.
在SecondActivity中创建一个打开FirstActivity的按钮.
先打开SecondActivity再打开FirstActivity, 结果如下:

android 后台弹出activity权限_android_03

singleTask

当Activity的启动模式指定为singleTask, 每次启动该Activity时, 系统首先会在返回栈中检查是否存在Activity的实例, 如果发现已经存在则直接使用该实例, 并把在这个Activity之上的所有其他Activity统统出栈, 如果没有发现就会创建一个新的Activity实例.

修改FirstActivity的启动模式为singleTask:

<activity
    android:name=".FirstActivity"
    android:launchMode="singleTask"
    android:exported="true">
    ...
</activity>

在FirstActivity中添加onRestart()方法, 并打印日志:

override fun onRestart() {
    super.onRestart()
    Log.d("FirstActivity", "onRestart")
}

在SecondActivity中添加onDestroy()方法, 并打印日志:

override fun onDestroy() {
    super.onDestroy()
    Log.d("SecondActivity", "onDestroy")
}

在FirstActivity中打开SecondActivity, 再打开FirstActivity, 结果如下:

android 后台弹出activity权限_java_04

singleInstance

指定为singleInstance模式的Activity会启用一个新的返回栈来管理这个Activity(如果singleTask模式指定了不同的taskAffinity, 也会启动一个新的返回栈).

如果我们让一个Activity可以被多个程序调用, 且这些程序可以共享这个Activity的实例, 使用其他三种启动模式是不行的, 因为每个应用程序都会有自己的返回栈, 同一个Activity在不同的返回栈入栈时必然创建了新的实例. 而使用singleInstance模式就会有一个单独的返回栈来管理这个Activity.

修改SecondActivity的启动模式为singleInstance

在FirstActivity的onCreate()方法中加入如下代码:

// 打印返回栈的实例
Log.d("FirstActivity", "Task id is $taskId")

在secondActivity的onCreate()方法中加入如下代码:

Log.d("SecondActivity", "Task id is $taskId")
// 打开ThirdActivity
binding.button4.setOnClickListener {
    val intent = Intent(this, ThirdActivity::class.java)
    startActivity(intent)
}

在ThirdActivity的onCreate()方法中加入如下代码:

// 打印返回栈的实例
Log.d("ThirdActivity", "Task id is $taskId")

运行程序, 在FirstActivity界面进入SecondActivity, 然后在SecondActivity界面进入ThirdActivity, 得到打印结果如下:

android 后台弹出activity权限_学习_05

可以看到SecondActivity的Task id不同于FirstActivity和ThirdActivity, 说明SecondActivity是存放在一个单独的返回栈里的, 而且这个栈只有SecondActivity.

此时, 在ThirdActivity界面按下Back键返回, 会回到FirstActiviy, 再返回会回到SecondActivity, 再按下会推出程序.
因为FirstActivity和ThirdActivity是放在同一个返回栈里的, 当ThirdActivity出栈, FirstActivity就成为了栈顶, FirstActivity再出栈, 当前返回栈就空了, 于是就显示了另一个栈的栈顶Activity, 即SecondActivity, SecondActivity再出栈, 所有返回栈就空了, 程序结束.

参考

郭霖. 《第一行代码 Android 第3版》