一.先理解栈的概念(放置Activity实例的容器)
1.Task(线性表)
任务栈Task,用来放置Activity实例的容器,先进后出,主要有2个基本操作:压栈和出栈,其所存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。
2.app启动时,系统会为它默认创建一个对应的Task,用来放置根Activity
ps: Activity之间可以相互启动,当前应用的Activity可以去启动其他应用的Activity(相机),那么就是说栈的功能可以把其它app的activity加入到自己app的栈里.
所以Task可以理解为负责管理所有用到的Activity实例的栈,但是.android5.0之后 跨进程调用activity,这个activity会被放入到一个新的栈中。
二.启动模式(只能根据压栈和出栈操作更改Activity的顺序,所以是启动模式是以哪种姿势入栈)
通过在AndroidManifest文件中的属性andorid:launchMode来设置或者通过Intent的flag来设置
1.standard(常规姿势入栈)
默认模式。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。应用场景:绝大多数Activity。
2.singleTop(栈顶复用姿势入栈)==FLAG_ACTIVITY_SINGLE_TOP
栈顶复用模式,如果要开启的activity在任务栈的顶部已经存在,就不会创建新的实例,而是调用 onNewIntent() 方法。避免栈顶的activity被重复的创建。应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。
3.singleTask(栈内复用姿势入栈)==FLAG_ACTIVITY_CLEAR_TOP
栈内复用模式, activity只会在任务栈里面存在一个实例。如果要激活的activity,在任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity,调用 onNewIntent() 方法,并且清空这个activity任务栈上面所有的activity(CLEAR_TOP回到栈顶)。应用场景:大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。
4.singleInstance(不入栈)
单一实例模式,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。
5.FLAG_ACTIVITY_NO_HISTORY
Activity使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中。
三.FLAG_ACTIVITY_NEW_TASK这个属性原则是:设置此状态,首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,同一个应用程序中的activity的亲和性一样),如果有,则直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。
1.getTaskId();获取当前activity所处的栈
2.同一个应用程序中的activity的亲和性一样(taskAffinity),也就是说 Actviitya intent时setFalg(
Intent.FLAG_ACTIVITY_NEW_TASK)到Activityb 但是Actviitya和Activityb 还是一个栈
在不同的应用中跳转才会创建新的Task。
3.在Activity上下文之外启动Activity需要给Intent设置FLAG_ACTIVITY_NEW_TASK标志,不然会报异常。
四 FLAG_ACTIVITY_CLEAR_TASK(必须和FLAG_ACTIVITY_NEW_TASK一起使用)
清空栈内activity,只留下这个activity