Task
官方文档 中关于task的解释:
任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。
task是可以跨应用的,这正是task存在的一个重要原因。有的Activity,虽然不在同一个app中,但为了保持用户操作的连贯性,把他们放在同一个任务中。例如,在我们的应用中的一个Activity A中点击发送邮件,会启动邮件程序的一个Activity B来发送邮件,这两个activity是存在于不同app中的,但是被系统放在一个任务中,这样当发送完邮件后,用户按back键返回,可以返回到原来的Activity A中,这样就确保了用户体验。
Lunch mode
1.android:launchMode
"standard"(默认模式)
默认。系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例
在这种模式下启动的activity可以被多次实例化,即在同一个任务中可以存在多个activity的实例,每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并且A已经启动,在A中再次启动Activity A,即调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前的桟中的状态为A-->A。
"singleTop"
如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的onNewIntent()方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。
如果A的启动模式为singleTop,并且A的一个实例已经存在于栈顶中,再次启动A时,不会再次创建A的实例,而是重用原来的实例,并且调用原来实例的onNewIntent()方法。任务桟中还是这有一个A的实例。
如果以singleTop模式启动的activity的一个实例已经存在与任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例。
"singleTask"
系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的onNewIntent()方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
在同一个任务中具有唯一性,至于会不会开启新的任务与taskAffinity有关。
taskAffinity: Activity 有着亲和关系的任务。从概念上讲,具有相同亲和关系的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)。 任务的亲和关系由其根 Activity 的亲和关系确定。
如果没有对activity设置该属性的话,默认为application的*taskAffinity*,如果application也没有设置,则为app的包名。
启动一个singleTask模式的activity,会首先在系统中找与它的taskAffinity属性一致的任务栈
1.没有特别指定taskAffinity,则为当前的task
2.如果指定了taskAffinity,先在系统中查找task,如果找不到则创建一个新的task,将activity作为root放置其中。
3.如果要启动的Activity已经存在、但没有位于Task栈顶,系统会将把位于该Activity上面所有Activity移出Task,从而使其转入栈顶。在该Activity之下的不变。
a1->a2->a3->a1, a1 按back,直接退出,不会回到a3.
4.如果需要在新的任务栈中启动,就需要为activity设置独立的taskAffinity.
5.如果当前activity是在新的任务栈中打开的话,那么之后在该activity中通过默认方式启动的activity都在这个新的任务栈。
"singleInstance"
与 "singleTask" 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。
1.具有全局唯一性,即整个系统中只会存在一个这样的实例
2.具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中。
3.被singleInstance模式的Activity开启的其他activity,能够开启一个新任务,但不一定开启新的任务,也可能在已有的一个任务中开启(根据taskAffinity)。
2.Intent flag
启动 Activity 时,您可以通过在传递给startActivity()的 Intent 中加入相应的标志,修改 Activity 与其任务的默认关联方式。可用于修改默认行为的标志包括:
在新任务中启动 Activity。如果已为正在启动的 Activity 运行任务,则该任务会转到前台并恢复其最后状态,同时 Activity 会在onNewIntent()中收到新 Intent
类似singleTask。
如果正在启动的 Activity 是当前 Activity(位于返回栈的顶部),则 现有实例会接收对onNewIntent()的调用,而不是创建 Activity 的新实例。
相当于launchMode中的singleTop,比如说原来栈中情况是A,B,C,D,在D中启动D(加入该flag),栈中的情况还是A,B,C,D
如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过onNewIntent()将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。
假设有A,B两个Activity,在AndroidManifest.xml中将A Activity的设置了android:clearTaskOnLaunch="true"。然后A中的操作启动了B,进入了B:(1)如果此时用户按了Home键回到主屏幕上,然后又点击了主屏幕上的A的icon图标启动应用。那么此时不是进入B,而是进入了A。(2)如果用户按了屏幕下方的”最近任务列表“键,调出最近任务列表中,出现的是B,用户点击,此时又进入的是B。
参考
Android中Activity四种启动模式和taskAffinity属性详解
Activity的任务栈Task以及启动模式与Intent的Flag详解
https://developer.android.com/guide/components/tasks-and-back-stack.html