(一)、基本描述
1. standard:标准模式:如果在 mainfest 中不设置就默认 standard;standard就是新建一个 Activity 就在栈中新建一个 activity 实例;
2. singleTop:栈顶复用模式:与 standard 相比栈顶复用可以有效减少 activity重复创建对资源的消耗,但是这要根据具体情况而定,不能一概而论;
3. singleTask:栈内单例模式,栈内只有一个 activity 实例,栈内已存 activity实例,在其他 activity 中 start 这个 activity,Android 直接把这个实例上面其他 activity 实例踢出栈 GC 掉;
4. singleInstance :堆内单例:整个手机操作系统里面只有一个实例存在就是内存单例;
在 singleTop、singleTask、singleInstance 中如果在应用内存在Activity 实例,并且再次发生 startActivity(Intent intent)回到 Activity后,由于并不是重新创建 Activity 而是复用栈中的实例,因此 Activity再 获 取 焦 点 后 并 没 调 用 onCreate 、 onStart , 而 是 直 接 调 用 了onNewIntent(Intent intent)函数;
(二)、taskAffinity 属性
taskAffinity 属性和 Activity 的启动模式息息相关,而且 taskAffinity 属性比较特殊,在普通的开发中也是鲜有遇到,但是在有些特定场景下却有着出其不意的效果。
taskAffinity 是 Activity 在 mainfest 中配置的一个属性,暂时可以理解为:taskAffinity为宿主Activity指定了存放的任务栈[不同于App中其他的 Activity的栈],为 activity 设置 taskAffinity 属性时不能和包名相同,因为 Android 团队为 taskAffinity 默认设置为包名任务栈。taskAffinity 只有和 SingleTask 启动模式匹配使用时,启动的 Activity 才会运行在名字和 taskAffinity 相同的任务栈中。
(三)、Intent 中标志位设置启动模式
在上文中的四种模式都是在 mainfest 的 xml 文件中进行配置的,Google Android 团队同时提供另种级别更高的设置方式,即通过Intent.setFlags(int flags)设置启动模式;
1. FLAG_ACTIVITY_CLEAR_TOP : 等 同 于 mainfest 中 配 置 的singleTask,没啥好讲的;
2. FLAG_ACTIVITY_SINGLE_TOP: 同 样 等 同 于 mainfest 中 配 置 的singleTop;
3. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS: 其 对 应 在AndroidManifest 中的属性为 android:excludeFromRecents=“true”,当用户按了“最近任务列表”时候,该 Task 不会出现在最近任务列表中,可达到隐藏应用的目的。
4. FLAG_ACTIVITY_NO_HISTORY: 对应在 AndroidManifest 中的属性为:android:noHistory=“true”,这个 FLAG 启动的 Activity,一旦退出,它不会存在于栈中。
5. FLAG_ACTIVITY_NEW_TASK: 这个属性需要在被 start 的目标 Activity 在AndroidManifest.xml 文件配置 taskAffinity 的值【必须和 startActivity发其者 Activity 的包名不一样,如果是跳转另一个 App 的话可以taskAffinity 可以省略】,则会在新标记的 Affinity 所存在的 taskAffinity中压入这个 Activity。
个人认为在上述 Flag中 FLAG_ACTIVITY_NEW_TASK 是最为重要的一个 flag,同时也需要注意的是网上有很多是瞎说的;而且也是个人唯一一个在实际开发中应用过的属性;先说说个人应用示例:
1.在 Service 中启动 Activity;
2.App 为系统 Launcher 时,跳转到微信无法退出时用到;至于为啥看下文开发的案例就知道了。
(四)、startActivity 场景
Activity 的启动模式的应用的设置是和它的开发场景有关系的,在 App 中打开新的 Activity 的基本上分为两种情况:
1. 目标 Activity 是本应用中的 Activity,即它的启动模式是可以直接在 Manifest中配置或者默认为 standard,任务栈也可以自己随意设置;
2. 目标 Activity 是第三方 App 中的 Activity,这个时候就需要先考虑打开新 Activity的是和自己 App 放在同一任务栈中还是新的 task 中【这个是很重要的因为在 Android 的机制中:同一个任务栈中的 activity 的生命周期是和这个task 相关联的[具体实例见下文]】,然后考虑 Activity 的启动模式; 所以Android 提供了优先级更高的设置方式在 Intent.setFlags(int flags),通过这 setFlags 就可以为打开第三方的 App 中 Activity 设置任务栈和启动模式了,具体设置就自己去看源码了。