前言
昨天在复习总结Activity相关知识的时候,无意中看到了启动模式,于是就想把启动模式总结下。那么启动模式有什么用?就是指定Activity该怎么运行,比如决定新开的Activity运行在调用方的任务栈中还是运行于一个新的任务栈等等
一、四种启动模式
下面所讲述的启动模式都是不加Intent的flag时的情形
1. standard(默认值)
该启动模式的Activity可以位于所有任务栈,每次启动都会新创建一个Activity实例,taskAffinity属性对该模式无影响,新启动的Activity始终与原有Activity同属于一个栈(前提是原有Activity的启动模式不是singleInstance)
- 例一 当应用程序A的A1 Activity启动应用程序B的B1(standard) Activity,B1会和A1同属 于一个栈(前提是A1的启动模式不是singleInstance)。
- 例二 当应用程序A的A1(standard) Activity不停的启动自己,那么栈中A1实例就会越来越多
2. singleTop
栈顶复用模式,该启动模式与standard的区别仅仅在于如果待启动的Activity已经处于目标栈顶了那么将不会再次创建实例,而只是调用该Activity的onNewIntent回调(其实会先调用onPause然后才是onNewIntent最后onResume)
- 例一 当应用程序A的A1(singleTop) Activity不停的启动自己,栈中还是只会有一个实例只是
onNewIntent不断的调用
3. singleTask
该启动模式的Activity整个系统的所有任务栈最多只能拥有一个实例,并且其启动后所在的任务栈是固定的,固定为特定taskAffinity的任务栈,如果任务栈中已经拥有了一个该Activity的实例那么不会再创建实例而是将该实例上面的所有Activity都关闭掉,然后调用该Activity的onNewIntent
- 例一 当应用程序A的A1 Activity启动应用程序B的B1(singTask) Activity,B1不和A1同属于一个栈(特别的当A1与A2的taskAffinity一致时会运行在同一个栈中)
- 例二 应用程序A有A1(singleTask)、A2两个Activity,A1启动A2,然后A2启动A1,这时候会发现任务栈中只有A1了。
4. singleInstance
该启动模式与singleTask的唯一区别就是其会运行在一个单独的栈中,并且该栈中不允许其它Activity 进入
二、返回页面问题
点击返回键,系统会关闭当前处于前台的任务栈栈顶的Activity如果处于前台的任务栈中的Activity都被关闭了就会将最近被切换到后台的返回栈切换到前台以此循环
- 例一 应用程序A有A1、A2(singleTask)两个Activity,应用程序B有B1一个Activity,A1启动A2然后切换回后台,启动B1,B1再启动A2,这时候点击返回键会返回哪个页面?答案是A1,因为当B1启动了A2时系统判定特定taskAffinity的任务栈中A2实例是否存在,如果存在就把包括A1、A2的任务栈整个切换回前台,所以点击返回键出现的是A1
三、通过设置常用Flags启动Activity
1. FLAG_ACTIVITY_NEW_TASK
该Flag有以下两个作用
- 第一个作用是使非Activity的Context可以启动Activity比如在Service里面启动一个Activity就得设置这个Flag
- 第二个作用是将启动模式为standard、singleTop、singleTask的Activity运行在特定taskAffinity的任务栈中。注意当设置了该Flag以后调用startActivityForResult将会立即返回(启动启动模式为singleTask和singleInstance的Activity自带该Flag)
-
例一 在不考虑修改了taskAffinity的情况下,当应用程序A的A1(standard) Activity通过添加
FLAG_ACTIVITY_NEW_TASK后启动自己会发现添加了该Flag与没加一样,还是会每次创建一个A1的实例压入栈,原因是添加了该Flag后系统会查询待启动的Activity也就是A1指定的taskAffinity栈是否存在,如不存在就创建该栈然后创建一个实例压入栈,如果存在也会创建一个实例压入栈。思考:如果在本例中A1的启动模式为singleTop、singleTask、singInstance又会怎么样?首先对singleTask和singleInstance无影响因为它们默认就设置了该Flag,对于singleTop在本例中也相当于没设置该Flag,点击启动不会创建新的实例只是会调用
onNewIntent -
例二 在不考虑修改了taskAffinity的情况下,当应用程序A的A1 Activity通过添加
FLAG_ACTIVITY_NEW_TASK启动应用程序B的B1(standard) Activity,一共会有几个任务栈?答案是2个,如果没设置这个Flag那么结果是1个,设置了以后系统发现B1指定的taskAffinity的栈还没启动就会启动然后创建B1将其压入栈思考:如果在本例中B1的启动模式为singleTop、singleTask、singInstance又会怎么样?首先对singleTask和singleInstance无影响因为它们默认就设置了该Flag,对于singleTop而言任务栈也会变成两个其原理与standard一致
2. FLAG_ACTIVITY_SINGLE_TOP
该Flag只对目标Activity启动模式为standard的Activity起作用,使其产生的行为与singleTop一致
3. FLAG_ACTIVITY_CLEAR_TOP
对于启动模式为standard的Activity来说,如果启动时发现在目标栈中已经有该Activity的实例了,那么会将该Activity及其上面的所有Activity全部销毁,然后重建该Activity,对于启动模式是singTop或者同时设置了FLAG_ACTIVITY_CLEAR_TOP与FLAG_ACTIVITY_SINGLE_TOP来说会将上面的Activity销毁然后回调该Activity的onNewIntent(并不会把自己销毁再重建)
四、启动模式的应用场景
- singleTop 比如一个App收到若干个通知每个通知都要打开同一个页面查看信息,这时候如果用户看完一个再点击另一个就不会再打开一个该界面而只会刷新数据
- singleTask 一般用于应用程序的首页,比如浏览器首页
- singleInstance 应用于社交App的分享界面(微博、QQ、微信等),注意这里有个问题,当A应用程序打开分享页面然后输入了部分内容后然后切到后台,打开B应用程序再次打开分享页面,这样由于分享页面是singleInstance因此会被复用,那么编辑过的内容也会被保留,如果不需要保留我们可以监听
onNewIntent,在该回调方法中清除编辑过的内容