目录
前言
在 Android 应用程序开发中,Activity 的启动模式对于任务管理和用户界面交互至关重要。Android 提供了四种主要的 Activity 启动模式,分别是 standard、singleTop、singleTask 和 singleInstance
。每种启动模式都有不同的特点和适用场景,开发者可以根据应用程序的需求选择合适的启动模式来控制 Activity 在任务栈中的行为。
本文将深入探讨这四种 Activity 启动模式的原理、特点和使用场景,帮助开发者更好地理解和应用这些启动模式,提升应用程序的性能和用户体验。
一、standard 模式
标准模式
,也是系统默认的启动模式。每次启动都会创建一个新的Activity实例,不管这个实例在栈中是否已经存上。Activity所在的任务栈为启动新Activity B的Activity A所在任务栈。具体就是Activity A所在的任务栈为S1,Activity A启动Activity B,那么Activty B的实例被创建后,会将Activity B的实例压入任务栈S1中。
二、singleTop 模式
栈顶复用模式
,如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
三、singleTask 模式
栈内复用模式
。这是一种单实例模式,在这种模式下,只要Activity在一个任务栈中存在,那么多次启动此Activity都不会创建新的实例。如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。SingleTask有clearTop效果,重用时,会让该实例回到栈顶,在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
四、singleInstance 模式
单实例模式
。这是一种加强版的SingleTask模式,在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
五、设置启动模式
5.1 AndroidMainfest清单
设置启动模式的位置在 AndroidManifest.xml 文件中 Activity 元素的 Android:launchMode 属性。
5.2 通过Flag动态设定
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
常见的Flags有
Flags | 作用 |
---|---|
FLAG_ACTIVITY_NEW_TASK | 设置此Flag不等价将LaunchModel设定为singleTask,仅仅表示将此Activity加入到TaskAffnity指定的任务栈中 |
FLAG_ACTIVITY_SINGLE_TOP | 将Activity的LaunchModel设定为singleTop |
FLAG_ACTIVITY_CLEAR_TOP | 将栈中Activity之上的其他Activity全部出栈,singleTask默认具有该属性 |
FLAG_ACTIVITY_EXCLUDE_FROM_TASK | 该Activity的不会出现在后台任务的列表中,和在Androidmainfest.xml中设定android:excludeFromRecents="true"同一个意思 |
5.3 优劣比较
Flags方式的优先级比在清单文件中的优先级高,两种方式同时设置时Flags的方式会生效
Flags方式不能设置singleInstance
六、任务栈名称
Android App在创建任务栈时,默认使用的是包名为任务栈名称,当然也可以自定义指定任务栈名称,比如:
<activity
android:name=".SecondActivity"
android:launchMode="singleInstance"
android:taskAffinity="com.example.task.task.SecondActivity11"
android:allowTaskReparenting="true"/>
其中,属性taskAffinity
与allowTaskReparenting
是配合使用的。
taskAffinity
指定任务栈名称。属性taskAffinity只有在SingleTask和SingleInstance模式下有效。
allowTaskReparenting
表示是否允许任务转移,即 Activity 从一个任务栈转移到另一个任务栈。如果将该属性设置为 true,则允许 Activity 被从一个任务栈转移到另一个任务栈中。这样可以在不同的任务栈之间移动 Activity,实现任务栈之间的交互和控制。
通过adb shell dumpsys activity activities 可以查看相关信息
每个任务栈都有自己的Task id,每个 Task id 都代表不同的任务栈
dumpsys activity activities |grep "Task id"
Task id #1066
Task id #1053
Task id #1056
Task id #1078
七、启动模式的适用场景
模式 | 场景 |
---|---|
Standard(标准模式) | 适合大多数情况,每次启动 Activity 都会创建一个新的实例,无论该 Activity 是否已经存在于任务栈中。适用于独立的任务流程或不需要对 Activity 实例进行特殊控制的场景。 |
SingleTop(单顶模式) | 从外界可能多次跳转到一个界面,适合需要频繁启动的 Activity,并且只有当该 Activity 不在栈顶时才创建新实例的情况。适用于需要处理类似“返回”操作或导航到同一 Activity 的场景,避免创建不必要的实例。 |
SingleTask(单任务模式) | 适合作为应用的入口点Activity,只允许一个实例存在于任务栈中。适用于需要“单例”行为的 Activity,例如主界面、登录界面等。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。 |
SingleInstance(单实例模式) | 适合独立于应用程序的 Activity,将其放置在一个新的任务栈中,用户可以通过不同任务栈来访问该 Activity。适用于需要独立处理的功能模块、特殊的活动界面等。例如闹铃提醒,将闹铃提醒与闹铃设置分离。 |