Activity启动模式LaunchModel有四种:standard、singleTop、singleTask,singleInstance。
可以在Activity标签下LaunchModel属性,配置不同启动模式,启动模式可以理解为任务栈模型,就是新创建的Activity是以哪种方式加入任务栈,而Activity任务栈是有AMS进行统一管理的。
1.standard:标准模式
如果Activity没有设置launchMode,默认就是标准模式,每开启一个Activity,就会创建它的一个实例。A-->B-->C-->D。按下Back键后,执行出栈,Activity依次退出销毁。
2.singleTop:栈顶复用模式。
如果新创建的Activity位于任务栈的栈顶,并且该Activity是singleTop模式,那么就不会创建新的实例,而是复用当前的Activity,调用它的onNewIntent方法,通过Intent把所需的参数传递进来。
例如:如果D设置的standard模式,在ABCD之后再开启一个D,任务栈中是这样的:
A-->B-->C-->D-->D.
如果的设置的是singleTop模式,在ABCD之后再开启一个D,栈中是这样的:
A-->B-->C--D.
因为D位于栈顶,符合栈顶复用模式,不会去创建一个新的D的实例,而是复用已经存在的实例。
实际开发中的应用场景:
新闻详情界面,详情下面有新闻列表,点击列表,需要打开新闻详情界面。
此时,新闻详情界面处于栈顶,无需开启新的Activity,可以把新闻详情界面设置为singleTop模式,在onNewIntent方法中,接收传递进来的intent,拿到url,重新加载就行。
3.singleTask:栈内复用模式。
在这种模式下,该Activity在一个任务栈中,无论是否是处于栈顶,无论启动几次,都会只有一个Activity,如果启动的Activity没有位于栈顶,那么在此Activity之上的Activity都会被销毁,从而把该Activity推到栈顶,调用它的onNewIntent方法。
比如,如果BActivity设置的是singleTask模式。任务栈中存在的实例如下:
A-->B-->C--D.
此时在开启一个BActivity,因为B设置的是singleTask模式,会销毁D C,该任务栈中只会保留一个B的实例,并把他推到栈顶,此时的任务栈中实例如下:
A--B。
如果B位于栈顶,那么和singleTop模式一样。
4.singleInstance:单实例模式
这种模式下,会为新开启的Activity创建一个单独的任务栈,并且只有一个实例。如果该实例已经存在,同样会调用它的onNewIntent方法,而不是重新创建新的实例调用onCreate方法。
AMS中任务栈的处理。
当我们通过startActivity,开启一个Activity时,会通过Binder通信通知AMS来处理Activity的出栈入栈操作。
在AMS中,有源码可以看到的。
在startActivityUncheckedLocked方法中,可以看到针对于任务栈的处理。
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(launchSingleInstance || launchSingleTask)) {
// We have a conflict between the Intent and the Activity manifest, manifest wins.
Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
"\"singleInstance\" or \"singleTask\"");
launchFlags &=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
switch (r.info.documentLaunchMode) {
case ActivityInfo.DOCUMENT_LAUNCH_NONE:
break;
case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
break;
}
}