Android 的四种启动模式,分别是 standard、singleTop、singleTask 和 singleInstance。四种启动模式都跟栈有关。
这里简单概况自己觉得比较容易一下子看懂的说法。
当没有在
AndroidManifest.xml里为<activity>配置android:launchmode时,所有的 Activity 默认都是以 standard 模式启动的。预先提醒好,Task 和 栈 是两个概念,最简单粗暴的说:
1. 栈是你看不见摸不着的,多个栈可以存在于同一个 Task 里;
2. 另一个 Task 启动后,你能在最近任务里看到它。
结尾有一个太长不看(虽然并不长)的总结。
standard - 默认模式
简单的说,就是你每次启动这个 Activity 时,无论情况如何,都会创建一个新的实例。比方说你打开了 MainActivity,这个 Activity 里有一个按钮 StartButton,点击后会完整启动 MainActivity。
此时的栈点击前:
- MainActivity // 原先的
- ...
点击后:
- MainActivity // 新的
- MainActivity // 原先的
- ...
即使栈里原本就有 MainActivity,此时还是会创建一个新的 MainActivity 实例,并且按顺序调用 onCreate()、onStart()、onResume(),与新的完全一样。
有关 taskAffinity,留到后面讲。
singleTop - 栈顶复用
跟 standard 不同,在上面的程序中,如果设置了 singleTop,并且当前 Activity 处于栈顶,在点击 StartButton 后,并不会重新创建实例,而是保留原本的实例(但会调用 onNewIntent())
也就是这个 Activity 在前台运行时,如果你还想启动这同一个 Activity,则并不会跟 standard 模式一样再创建实例,即并不会调用
onCreate()、onStart()
此时的栈点击前:
- MainActivity // 原先的
- ...
点击后:
- MainActivity // 原先的 &“新”的
- ...
但是此时会调用 MainActivity的 onNewIntent() 方法。
对了,如果前面前提不成立,当前 Activity 不在栈顶呢?那就跟 standard 模式一样重新创建实例,比如:
此时的栈点击前:
- OtherActivity
- MainActivity // 原先的
- ...
点击后:
- MainActivity // 新的
- OtherActivity
- MainActivity // 原先的
- ...
有关 taskAffinity,留到后面讲。
singleTask - 栈内复用
其实看到名字可以以此类推了,singleTask 模式下,只要栈里有 MainActivity,就会直接将 MainActivity 上方的所有 Activity 全部出栈,让 MainActivity 回到栈顶。
“这个栈里只能容得下一个👴!”
此时的栈点击前:
- AnotherActivity
- OtherActivity
- MainActivity // 原先的
- ...
点击后:
- MainActivity // 原先的 &“新”的
- ...
MainActivity 上方的两个 Activity 都被出栈了。
这一部分需要讨论 taskAffinity(终于)
taskAffinity 也是 <activity> 的一个属性,即 android:taskAffinity。未设置的情况下,其默认值为包名。
是的,如果设置了与包名不一样的 taskAffinity,其对应的 Activity 的 Task 就发生了改变。下面假定 Activity 启动顺序为:
- 未设置
taskAffinity的OtherActivity(默认 standard 模式) - 设置了
taskAffinity的MainActivity(指定 singleTask 模式) - 未设置
taskAffinity的AnotherActivity(默认 standard 模式)
所以:
- 在启动了
OtherActivity后启动MainActivity,由于MainActivity的启动模式是singleTask,此时 Android 会查找其taskAffinity。在这里会发现它的taskAffinity并非与包名相同,因此会创建一个新的 Task,并将MainActivity放入其中(此时MainActivity与OtherActivity处于不同的 Task 中); - 然后,启动
AnotherActivity。因为AnotherActivity使用的是 standard 模式,Android 无需去寻找其taskAffinity的值,只要跟着之前的 Activity 就行,因此此时的AnotherActivity会进入MainActivity所在的栈。
之前:
- OtherActivity
- ...
之后:
旧栈
- OtherActivity
- ...
新栈
- AnotherActivity
- MainActivity
- ...
这里可以看到,设置了
taskAffinity的MainActivity启动后,由于切换到了新栈,启动AnotherActivity的话,它不会回到旧栈,而是在新栈中成为栈顶。
singleInstance - 全局唯一
跟 singleTask 差不多,但是使用此启动模式创建的 Task,整个 Task 里只有它自己一个。直接上例子可能会好一点。
我们预先设定 OtherActivity 使用 standard 模式,MainActivity 使用 singleInstance 模式。
当两者 taskAffinity 相同时
此时会创建新的 Task 且独一无二,点击启动 MainActivity 前:
- OtherActivity
- ...
点击后:
原来的 Task
- OtherActivity
- ...
新的 Task
- MainActivity
- ...
但是这里注意,如果我在 MainActivity 里再想启动 AnotherActivity 时:
原来的 Task
- AnotherActivity
- OtherActivity
- ...
新的 Task
- MainActivity
- ...
是的,新的 Activity 并不会进入到新的 Task 里, 所以说 singleInstance 创建的 Task 是独一无二的。
当两者 taskAffinity 不同时
表现上与 taskAffinity 相同时一致,但是可以在最近任务里看到。
总结
简单来说:
standard
你想创建新实例就创建吧,随你,叠千层饼都行。
singleTop
如果你想启动你面前(栈顶)的 Activity 的话,除了会调用它的
onNewIntent()外没什么变化。除此之外,跟 standard 一样。
singleTask
taskAffinity相同的时候(不设置的时候也相同),如果之前开过这个 Activity(还在栈里),就直接把它拽到最前面,其他的统统废掉(栈中在它上方的全部出栈);
taskAffinity不相同的时候,启动这种 Activity 后,它会脱离于原来的 Task,新开一个,而且新顾客也会跟着它到新的地方去(后续启动的 Activity 会跟随着进入到新的 Task)。而且你能在最近任务里看到它有别于原来的 Activity(后台里任务卡片大于一张)。
singleInstance
taskAffinity相同的时候(不设置的时候也相同),启动这种 Activity 后,它会脱离于原来的 Task,新开一个,但是新顾客不会跟它走,新顾客还是会回到老的地方去(后续启动的 Activity 会在原来的 Task 中启动);
taskAffinity不相同的时候,启动这种 Activity 后,它跟taskAffinity相同的时候一样,唯一不同的是你能在最近任务里看到它有别于原来的 Activity(后台里任务卡片大于一张)。
Tips
- taskAffinity 是否相同会直接影响到后台是否在同一张任务卡片里。
参考:
共有 0 条评论