任务和后台栈定义
任务(Task)是用户在执行某项工作的时候所有活动(Activity)的集合。并且这些活动都存储在一个栈中,这个堆栈就是后台栈。后台栈遵循“后进先出”原则,当启动一个Activity时,这个activity会被压入栈顶,当按下回退按钮时,栈顶Activity被弹出,当栈中所有Activity都被弹出的时候,这个后台栈就不存在了。
定义加载模式
加载模式允许我们定义一个Activity的实例是如何和当前任务交互的。我们可以使用两种方法为一个activity定义加载模式:
- 使用Manifest文件配置
<activity
android:name="....."
android:launchMode="standard|singleTop|singleTask|singleInstance">
</activity> - 在代码中使用flag
Intent intent = new Intent(ActivityA,ActivityB);
intent.setFlag(Intent.xxxxxxxx);//设置flag
startActivity(intent);
****需要注意的是某些在manifest中可以配置的加载模式不能在代码中指定,同样,某些可以在代码中指定的加载模式不能在manifest中配置。但是在代码中指定的话会覆盖掉Manifest文件中配置的。****
launchMode在Manifest下的种类
- standard(默认模式)
这种模式下,每次有意图导向activity时系统都会创建一个activity的实例,activity可以被重复创建,每个activity 的实例可以属于不同的任务,一个任务中可以有多个相同activity的实例。
举个例子,A(standard)与B(standard)两个activity,以A-B-A-B-B的顺序依次启动的话,需要连按五次回退按钮才能退出栈 - singleTop
当目前任务中已经有一个activity的实例存在于栈顶的话,系统会使用那个activity的onNewIntent方法启动那个actviity,而不是再新建实例。
举个例子,后台栈中已经有以A-B-C-D顺序排列的activity(D在栈顶)。此时再启动D,如果D的launchMode是“singleTop”的话,栈顶D执行onNewIntent方法,由于D此时是栈顶元素,所以此时顺序依旧是A-B-C-D,需要按四下回退按钮才能退出栈。然而如果此时启动的是B(standard 或者singleTop)的话,由于B不在栈顶,所以系统新建B的实例,此时顺序为A-B-C-D-B,需要按五下退出栈。 -
singleTask
系统会创建一个新的任务并且在这个任务的根上实例化这个activity。然而,当系统另外的任务中存在这个activity 的实例的话,系统会调用这个activity的onNewIntent方法,而不是新建一个实例。换句话说,系统中只会存在一个activity的实例。
举个例子:A(standard)与B(singleTask),有一个顺序A-B-A存在于栈中,此时再启动B,这个时候第三个A被弹出栈,第二个B被复用,此时栈中顺序为A-B,所以当启动launchMode为singleTask的activity时,系统会弹出这个activity存在的任务栈中所有在它上面的activity。所以Launcher可以用这个加载模式启动应用。
在举个例子如下图(来自官方文档):
diagram_backstack_singletask_multiactivity.png
A(standard)与B(singleTask),当一个app的任务栈中顺序为A-B-A,此时在另外一个app(顺序为C)中通过隐式意图启动B时,会弹出第三个A并且把A-B插入后面那个app的任务栈中,此时顺序变为C-A-B。
- singleInstance
和“singleTask”差不多,但同一个任务栈中只有一个唯一的activity 的实例,这个任务栈不会加载其他activity。
举个例子:A(standard)与B(singleTask),有一个顺序A-B-A存在于栈中,此时再启动B,第二个B被复用,B被换到栈顶,此时顺序为A-A-B,只是简单复用而不会弹出其他的activity
flag中的加载模式
最主要是在隐式Intent中使用,指定要启动的Activity要以什么模式加载。
- Intent.FLAG_ACTIVITY_NEW_TASK
行为等同于"singleTask" - Intent.FLAG_ACTIVITY_SINGLE_TOP
行为等同于"singleTop" - Intent.FLAG_ACTIVITY_CLEAR_TOP
如果将要被打开的Activity已经在当前任务中运行的话,所有其他在它顶上的Activity会被destroy并且这个intent会通过onNewIntent方法使被打开的Activity的状态变为resume。
Clearing the back stack
当用户离开一个任务很长时间后,系统会清除除了root activity之外的其他activity。当用户再次回到这个任务时,只有根activity会被启动。因为一般来说当用户离开一个任务很长时间后会丢弃之前做的事。
下面有几个属性可以改变这个行为:
-
alwaysRetainTaskState
当在根Activity中设置这个值为true时,系统会一直保存这个任务下的所有activity实例。 - [clearTaskOnLaunch]
(https://developer.android.com/guide/topics/manifest/activity-element.html#clear)
当在根Activity中设置这个属性为true时,只要用户离开了这个任务的话,系统就会清除栈中所有除了根Activity的Activity,当再次回到这个任务时会加载根Activity的初始状态。 -
finishOnTaskLaunch
和clearTaskOnLaunch相似,但是这个是针对单个Activity设置的,当为某一个Activity设置此属性为true的话,只要用户离开任务的话,这个Activity就会被finish。