今天来唠唠 任务栈 和 返回栈 。
作者:秉心说TM
任务栈?返回栈?
关于 任务栈和返回栈,我看了 N 篇博客,说的最清楚的除了 重学安卓 ,那就非 官方文档 莫属了。其实大多时候,很多模糊不清的基本概念,从官方文档都可以轻松的得到你想要的答案。
官方文档中这一节的标题叫做 Understand Tasks and Back Stack ,Task 就是我们常说的 任务栈,Back Stack 就是返回栈。
任务栈很好理解,Activity 们是存在一个栈结构中的,后进先出,这也很符合实际的使用场景。
依次打开 Activity1
,Activity2
,Activity3
,它们依次入栈,如上图所示。然后连续按下两次返回键,Activity3
和 Activity2
会依次出栈。
那么,返回栈呢?
什么是返回栈?
返回栈的作用是什么?
返回栈和任务栈的区别是什么?
灵魂三连拷问,不知道你能不能清晰的给出答案。这里暂且按住不表,我们先来看看 影响任务栈和返回栈的因素 有哪些?
我们从 launchMode(启动模式) 开始说起。
启动模式
声明启动模式有两种方式:
- 在清单文件中声明待启动的 Activity 的 launchMode 属性
- 代码中通过 Intent 启动 Activity 时,设置 flag
如果在一次启动过程中,两种方案都设置了,后者优先级比较高。
清单文件的 launchMode 和 intent flag 都不能完全代替对方。
launchMode
属性有四种取值 : standard
、 singleTop
、 singleTask
、 singleInstance
。
standard: 标准启动模式
也是默认的启动模式,每次启动 Activity 都会新建一个新的实例。待启动 Activity 会进入源 Activity 所属任务栈。
同一个 Activity 可能被实例化多次 。
singleTop: 栈顶复用模式
待启动 Activity 已经位于源 Activity 所属的任务栈的栈顶时,不会创建新的 Activity,而是直接使用栈顶的 Activity,并回调它的 onNewIntent 方法,onCreate 和 onStart 不会被调用,直接回调 onResume 。
否则的话,在栈顶创建一个新的 Activity 实例。
singleTask:栈内复用模式
全局单实例,首先会寻找要启动的 Activity 想要的任务栈(默认或者 taskAffinity
属性指定),如果没有找到,则创建新的任务栈并将 Activity 实例放入。如果找到了想要的任务栈,这时候要判断栈中是否已经存在该 Activity 的实例,如果已经存在,会将该 Activity 以上的其他 Activity 实例弹出,把自己放到栈顶,同样也是回调 onNewIntent
和 onResume
。如果实例不存在,创建新的实例并压入栈中。
singleInstance:单实例模式
全局单实例,首次启动时会创建新的 Activity 实例,并放入一个新的任务栈中,且 这个任务栈中只会有这一个实例。 后续启动不会再新建实例。
默认的 standard 模式其实已经满足大部分情况下的需求,但是 同一个 Activity 会创建多次实例 在某些情况下肯定是不合适的,返回栈也会很突兀。这时候就需要复用已经存在的 Activity 实例,所以有了 singleTop
和 singleTask
两种不同的复用方式。而 singleInstance
则更加直接,Activity 实例和任务栈都是全局唯一的。
另外注意一点,singleTask
的 Activity 实例也是全局唯一的。可能有的人会问,在不同的任务栈中可能会存在重复的启动模式为 singleTask 的 Activity 实例吗?其实你仔细想一下就能发现,这是做不到的。
taskAffinity
前面提到了 Activity 想要的任务栈, taskAffinity
的作用就是指定想要的任务栈。但它并不会在任何场景下都会起作用。
未显式声明 taskAffinity 的 Activ