ActivityManagerService(AMS)内部维护着一个ActivityStack栈,系统会将Activity实例一一放入栈内(先进后出),默认情况下创建一个实例压入栈内。如果多次创建同一个Activity,栈内将压入多个实例。为此,Android提供了启动模式来修改系统的默认行为。目前有四种启动模式:standard、singleTop、singleTask和singleInstance。
一、代码
BaseActivity:
MainActivity:
OtherActivity:
布局文件activity_main.xml,activity_other.xml文件与此类似
二、测试
1、standard
两个Activity都没有设置启动模式,即默认为标准模式。然后启动App,点击Start Main Activity按钮,然后再点击Start Other Activity按钮,然后再点击Start Main Activity。日志输出如下:
上述日志中所有的hashCode都不相同,即每次启动Activity都创建一个新的实例。连续按四次返回键退出应用。
TaskId都相同,表明这些实例都在同一个任务栈里。
2、singleTop
在AndroidMainfest.xml文件中,为MainActivity添加属性:android:launchMode=”singleTop”。启动App、点击Start Main Activity按钮、再点击Start Other Activity按钮,再点击Start Main Activity。日志输出如下:
第一次点击Start Main Activity按钮时,调用了onNewIntent方法,且hashCode与之前的MainActivity实例的hashCode相同,即复用实例而不是重新创建。第二次点击Start Main Activity按钮时,也就是说从OtherActivity里启动MainActivity,此时调用了onCreate方法,而且hashCode与之前的不相同,即重新创建了MainActivity的实例。连续按三次返回键退出应用。
TaskId都相同,表明这些实例都在同一个任务栈里。
3、singleTask
将MainActivity设置为singleTop,然后执行之前相同的动作。日志输出如下:
此时发现MainActivity的实例都相同,即第一次创建后,后面的都是复用实例而不是重新创建。按一次返回键退出应用。
TaskId都相同,表明这些实例都在同一个任务栈里。
4、singleInstance
将MainActivity设置为singleInstance,然后执行之前相同的动作。日志输出如下:
I/Xian Xiaotao: onCreate:MainActivity hasCode:29797800 TaskId: 529
I/Xian Xiaotao: taskAffinity:com.xianxiaotao.launchmode
I/Xian Xiaotao: onNewIntent:MainActivity hasCode:29797800 TaskId: 529
I/Xian Xiaotao: taskAffinity:com.xianxiaotao.launchmode
I/Xian Xiaotao: onCreate:OtherActivity hasCode:42572600 TaskId: 530
I/Xian Xiaotao: taskAffinity:com.xianxiaotao.launchmode
I/Xian Xiaotao: onNewIntent:MainActivity hasCode:29797800 TaskId: 529
I/Xian Xiaotao: taskAffinity:com.xianxiaotao.launchmode
此时发现MainActivity的实例依然相同,即第一次创建后,后面的都是复用实例而不是重新创建。按两次返回键退出应用。
TaskId不同,即MainActivity与OtherActivity不在一个Activity中。
读者可以通过多个Activity设置不同的启动模式进行复杂的测试。
三、结论
standard
标准模式,也是系统默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。ABCBB
singleTop
栈顶复用模式。如果新Activity已经位于任务栈的栈顶,那么只调用它的onNewIntent方法实现复用,而不会创建新的实例。如果新的Activity的实例已存在但不是位于栈顶,仍然重新创建。假设目前栈内情况为ABCD(ABCD为四个Activity,A位于栈底),此时再次启动,如果D的启动模式为singleTop,那么栈内仍然是ABCD;如果D的启动模式为standard,D将被重新创建,栈内情况变为ABCDD。
singleTask
栈内复用模式。在同一个栈内,它是单实例模式。在这种模式下,启动一个Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例并压入栈内;如果存在所需的任务栈,这时要看A是否在栈中有实例存在,如果有,那么系统就会把A调到栈顶并调用它的onNewIntent方法,不存在就创建并压入栈中。
1、目前任务栈栈S1(ABC),此时Activity D以singleTask模式请求启动,其所需的任务栈为S2,由于S2和D的实例均不存在,所以系统先创建任务栈S2,然后再创建D的实例并将其放入栈S2中。
2、另外一种情况,假设D所需的任务栈为S1,上述S1已存在,所以系统会直接创建D的实例并压入栈S1内。
3、如果D所需的任务栈为S1,其中为ADBC,此时系统将D上面的Activity出栈,把D切换到栈顶并调用onNewIntent方法,最终S1栈内为AD。
singleInstance:
该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。