前言
我们平常在开发APP时,在配置清单里面注册一个Activity 会经常用到它的launchMode属性 这个其实就是Activity的启动模式 相信这一块大家都不陌生 我们的一个APP启动时,会有一个属于自己的Task任务栈 里面放入的就是我们的Activity 比如我们分别启动了A、B、C三个Activity 那么任务栈就是这样的: 显示在屏幕的就是页面C 每个Task都会维护自己栈内的Activity 点击返回,就会按照顺序关闭最上层的Activity 这其实就是默认的启动模式standard
taskAffinity
在安卓里,一个APP默认只有一个Task存活在最近任务列表界面 用来区分是否是相同的Task,是根据Task的taskAffinity属性来决定的 一个Task默认使用栈底的Activity的taskAffinity属性来确定自己的taskAffinity属性 而Activity的taskAffinity属性,默认来源于Application的taskAffinity 而Application的taskAffinity属性,默认来源于包名 于是我们可以说: 一个APP里面的Activity,默认情况下,它们的taskAffinity都是包名
standard
standard模式下,每次都会去创建一个新的Activity,然后放入我们的任务栈中,这个不用多介绍 当我们点击最近任务键,就可以看到我们一个个APP的Task任务栈 比如我们打开一个APP,然后按下返回按钮关掉这个APP 会发现最近任务界面,还是有这个APP的Task。 难道APP并没有退出? 其实不是的,此时APP已经退出了 只不过你在最近任务再次点击这个任务栈, 系统会重新帮你创建Activity罢了 这就需要我们知道: 最近任务显示的Task,不代表APP就存活着 同样还有一种场景 如果我们在一个APP里面打开另外一个APP的Activity 启动模式为standard 那么另外一个APP的Activity,也会被放入当前APP的栈顶 就好像这样:
singleTop
如果Activity的启动模式为singleTop 那么基本和standard是一样的 只不过如果这个Activity在栈顶 那么就不新建,而是走onNewIntent方法
singleTask
如果Activity的启动模式为singleTask,那么当Activity被别的APP启动时 并不会和standard模式一样,放入别的APP的Task 而是直接放入自己的Task 同时连同自己的Task一起堆在别的APP的Task上面 类似下图这样,B进程的Task直接堆在了A进程的Task上面 这种情况点击返回时 回退的就是B进程的Task的页面 直到B进程回退完,才会显示A进程的Task然后继续回退 直到显示桌面 注意点一: 当你点击Home或者最近任务键时 两个Task就会被拆分开 最近任务列表就变成了下面这样: 这时候你再点击进入B进程,然后点击返回 当B进程Task的任务都返回后,就会直接显示桌面了 注意点二: 当B进程的这个singleTask的Activity页面已经存在Task里面时 这个Activity不会被再次创建,而是调用自己的onNewIntent方法 同时把压在自己上面的页面给移除掉 让自己显示在Task栈顶 如下图: 所以,singleTask的Activity 在一个Task里面只有一个 注意点三: 当一个进程A启动singleTask的Activity时 系统会去对比他们的taskAffinity 如果相同: 这种情况就是启动了自己APP里面的singleTask的Activity,直接把Activity放入Task即可 如果不同: 说明是别的APP的Task启动了这个Activity,于是这个Activity拿着自己的taskAffinity去最近任务列表中找。找到了和自己taskAffinity一致的Task,就进入这个Task,找不到,就新建一个Task,把自己丢进去。
singleInstance
singleInstance的Activity更极端 它被启动时, 要自己独占一个Task 然后堆在启动他的Activity所在的Task的上面 如果之前已经创建,也是调用onNewIntent方法进行复用 当点击Home或者最近任务键时 这两个Task也会拆分 如果在singleInstance的Activity上面再启动一个Activity 那么会把这个新启动的Activity的Task栈整个的拿过来 堆在singleInstance的Activity的Task栈上面 如下图: 这里,如果进程B的Activity不是启动的进程C的Activity 而是又启动了进程A的页面A 那么进程A的Task就会从底部拿出来 然后堆在singleInstance的Task栈上面 Task的堆放情况就会变成这样:
这里还有一个注意点: 假如B进程已经在最近任务界面有一个Task了 而这个singleInstant的Activity因为和B进程的Task的taskAffinity是一样的 所以这个Activity的Task在最近任务界面是看不到的 因为最近任务针对相同的taskAffinity的Task 只会显示一个 但这个Activity又是实实在在存在的,只是看不见 所以我们也可以说: 在最近任务界面看不到的Task,未必就不存在
|