1.Activity的启动模式

当我们多次调用同一个Activity时,系统会重复创建多个实例并把它们一一放入任务栈中,这种方式显然不符合我们的设计要求。所以Android在设计时就提供了四种启动模式来解决此问题。

四种启动模式分别如下:

  1. standard-标准模式也是默认模式
    每次启动一个Activity都会创建新的实例并压入任务栈,onCreate,onStart,onResume都会被调用。每个任务栈可以有多个实例,每个实例也可属于不同的任务栈。例如:
    A->B,B为standard模式,B即属于A的任务栈。
    A B C D 再次启动A(standard模式)
当前任务栈存在的元素 启动后的任务栈存在的元素
A B C D A B C D A
  1. singleTop-栈顶复用模式
    此模式下,比如新的Activity已经位于栈顶,那么此Activity不会被重新创建,会回调它的onNewIntent方法,它的onCreate,onStart不会被系统调用。如果新的Activity不是位于栈顶,那么它还是会被重新创建。例:
    A B C D 再次启动D(singleTop模式)
    A B D C 再次启动D(singleTop模式)
当前任务栈存在的元素 启动后的任务栈存在的元素
A B C D A B C D
A B D D A B D C D
  1. singleTask-栈内复用模式
    单实例模式,只要Activity在一个栈中存在,多次启动都不会重新创建实例,系统会回调onNewIntent方法。
    如果要启动一个启动模式为singleTask的Activity A,先判断是否存在A所需的任务栈,不存在->新创建任务栈并把实例A压入。如果存在,判断A是否在栈中存在实例,存在移到栈顶,并将之前的实例出栈,如果不存在实例,创建并压入栈。
任务栈S1存在A B C,启动D(singleTask模式)(所需任务栈S2),因为S2与D实例均不存在,所以系统会新建任务栈S2并创建D压入S2。
任务栈S1存在A B C,启动D(singleTask模式)(所需任务栈S1),启动D后的S1为A B C D。
任务栈S1存在A D B C,启动D(singleTask模式)(所需任务栈S1),启动D后的S1为A D。

使用:

<activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
</activity>

 override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        Log.d(TAG, "--onNewIntent--")
    }

Android四大组件之Activity-启动模式

可以看出MainActivity始终没有被重新创建

  1. singleInstance-单实例模式
    加强的singleTask模式,拥有singleTask的所有特点且只能单独的位于一个任务栈中。

特殊情况

?:现在有S1-前台任务栈,S2-后台任务栈(singleTask模式)。S1有A B,S2有C D。
现在启动D,S2整个任务栈会切换至S1中,即S1存在 A B C D,依此按下返回键实例一一出栈。
现在启动C,S2整个任务栈会切换至S1中,即S1存在 A B C,依此按下返回键实例一一出栈。

2.任务栈

前面所说的Activity所需任务栈是什么?即TaskAffinity参数:这个参数标识了一个Activity所需任务栈的包名。此属性主要与singleTask启动模式或者allowReparenting属性配对使用。

1.当与singleTask配对使用时,启动的Activity会运行在名字与TaskAffinity相同的任务栈中。
2.当与allowReparenting配对使用时,情况比较特殊。
现有应用A与B(存在Activity C),现在A启动B的C,点击Home键。点击B 会启动C。--C从A的任务栈转移到了B的任务栈。

简单使用:
A为standrad
B为singleTask TaskAffinity值为”com.wdl.test“。模拟过程A->B->A

    <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".Main2Activity"
            android:taskAffinity="com.wdl.test"
            android:launchMode="singleTask"/>

控制台输入adb shell dumpsys activity

Android四大组件之Activity-启动模式

发现此时存在两个任务栈 一个为包含B A的S1(com.wdl.test),另一个为只有A的S2 (com.wdl.kt1)

分为2类:

  • 前台任务栈
  • 后台任务栈,位于暂停状态

3.如何给Activity指定启动模式

  1. 通过AndroidMenifest.xml为Activity指定启动模式
  <activity android:name=".Main2Activity"
            android:launchMode="singleTask"/>
  1. 在Intent中设置标志位为Activity指定启动模式
  val intent = Intent(this,MainActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(intent)

常用的标志位有:

作用
FLAG_ACTIVITY_NEW_TASK 指定singleTask启动模式
FLAG_ACTIVITY_SINGLE_TOP 指定singleTop启动模式
FLAG_ACTIVITY_CLEAR_TOP 此Activity(singleTask)之前的实例全部要出栈; Activity(standard)之前与本身的实例全部要出栈,重新创建实例并入栈
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有此标记的Activity不会出现在历史Activity中

二者的区别:
1.优先级上第二种方式高于第一种方式
2.限定范围上有所不同
例:第一种方式无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识;第二种方式无法为Activity指定singleInstance模式

相关文章:

  • 2021-11-19
  • 2021-07-30
猜你喜欢
  • 2021-12-25
  • 2022-01-17
  • 2021-12-26
  • 2022-12-23
  • 2021-11-08
  • 2021-12-02
相关资源
相似解决方案