Android程序员面试笔试宝典
上QQ阅读APP看书,第一时间看更新

1.1.2 启动模式

启动模式的意思就是一个Activity是以怎样的一种启动方式来跳转到当前页。设置启动模式的方法也有两种。第一种用得比较多:在配置文件AndroidManifest.xml里用android:launchMode来指定,有四种模式可指定,分别是standard、singleTop、singleTask和singleInstance。这四种模式将在本节中逐一详细讲解;第二种设置方式则是通过在Intent中设置标记位来指定启动模式。

在讲解启动模式之前,还需要知道“任务栈”的概念。什么是任务栈?任务栈,即Task,它是一种用来保存和管理Activity的数据结构,也是所有Activity的集合。它遵循“后进先出”规则,假如当前页是ActivityA,点击按钮启动ActivityB,此时ActivityB就入栈,处于栈顶位置,而ActivityA则位于ActivityB之下,所以当前页就跳转为ActivityB了。这就是正常的启动模式,而往往实际开发中有时并不会只想要正常的启动模式,这时就需要用到上文提到的两种方式来指定其他启动模式了,尤其是第一种方式的四种模式是最常用的。

(1)standard

标准模式,如果不指定android:launchMode,默认就是standard模式。它就是常说的正常情况下的模式,每次启动一个活动时,就会创建一个实例,然后被启动的活动入栈,并处于栈顶的位置。

下面通过代码来实现standard模式,在MainActivity的onCreate()方法里用Intent来实现跳转,而这里决定让MainActivity要跳转的活动是自己,因为这样能更好地看出在standard模式下活动是怎样启动的:

然后连续点击按钮3次,打印结果如下:

从运行结果可以看出,MainActivity的确是被创建了3个实例,每启动一次,就创建一个新实例。

(2)singleTop

在该模式下启动Activity,系统会先检查任务栈栈顶是否有该Activity实例,如果有则直接使用它,调用onNewIntent()方法;如果没有则创建新的实例并且入栈到栈顶。设置该模式的方法就是在AndroidManifest.xml文件里用android:launchMode来指定:

MainActivity.java里的代码不变,运行程序,然后再次连续点击3次跳转按钮,打印结果如下:

从运行结果可以看出,不管按多少点跳转按钮,MainActivity只有一个实例,因为它在栈顶位置了,只需直接使用它就可以,不需要创建新的实例。

(3)singleTask

经过上文讲解,可以知道singleTop是栈顶复用活动实例:活动A设置了singleTop模式,当活动A启动活动B,然后活动B再启动回活动A时,因为此时处于栈顶位置的是活动B而不是活动A,所以还是会创建新的活动A实例,这是singleTop模式的效果。但是如果实际开发中有需求是要求整个应用就只存在活动A一个实例,不管怎么启动,都只使用这一个实例,那又该如何实现呢?所以此时就需要设置singleTask模式了:

然后创建另一个活动类BActivity,用它来启动MainActivity:

最后MainActivity改为启动BActivity:

运行程序后,先点击MainActivity的按钮启动BActivity,然后再点击BActivity的按钮启动MainActivity,打印的结果如下:

从运行结果可以看出,当在BActivity里点击按钮启动了MainActivity后,并没有创建新的MainActivity实例,这就是singleTask模式的作用了。

这里要再介绍一个知识点就是taskAffinity属性。该属性跟singleTask是密切相关的,因为其实该模式下启动活动时,最先开始还有一个任务栈匹配的过程,就是会先根据需要的任务栈里找活动实例,而这个需要的任务栈就是通过taskAffinity属性来指定的。当然也可以不指定,这样就默认为taskAffinity值为包名。

所以,最后来总结一下singleTask模式:如果是在同一个应用中(taskAffinity值一样)启动Activity时,系统先检测任务栈中是否存在该Activity,如果存在则直接使用该活动实例,让它置于栈顶,而它之上的其他活动纷纷出栈。如果不存在该实例,则创建该活动新的实例,置于栈顶。如果不是在同一应用中(taskAffinity值不一样),而是其他应用中来启动该模式下的Activity时,那么系统会创建一个新的任务栈,创建该活动新的一个实例,将它置于该新建任务栈栈顶。

(4)singleInstance

在该模式下启动Activity时,系统会先创建一个新的任务栈来专门存储与管理该Activity,而且该Activity具有全局唯一性,也就是该任务栈中只有这个Activity实例,任何应用只要启动该Activity,用的都是这一个实例。下面用代码实现该模式下的效果,先把MainActivity设置为singleInstance模式:

然后把MainActivity的任务栈id打印出来:

接着也把BActivity的任务栈id打印出来,最后运行程序,在MainActivity页面里点击按钮跳转启动BActivity,然后在BActivity页面里点击按钮跳转启动MainActivity,打印的结果如下:

从运行结果可以看出,两个活动各自所处的任务栈是不一样的,而且最后MainActivity也只有一个实例,这就是singleInstance模式的作用了。