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 条评论