Activity四种LaunchMode详解

大家都知道Activity有四种LaunchMode,分别是standard、singleTop、singleTask、singleInstance。通过打Log的方式测试,我们可以知道每一种LaunchMode的情况下,Activity是否会重新创建实例,是否会重新创建Task,网上也有很多帖子作了很详细的解释,因此这里不再详细地测试每一种LaunchMode下具体情况,只是做一个总结,方便自己也方便大家记忆与使用。
首先需要简单介绍一下Task,本文中称作任务栈。Task是在程序运行时,一组相互关联的Activity 的集合,它是framework层的一个概念,控制界面的跳转和返回。这组Activity 是以栈的形式存在于一个称为back stack的数据结构中。这个栈的基本行为是,当用户在多个Activity 之间跳转时,执行压栈操作,当用户按返回键时,执行出栈操作。Task是可以跨应用的,这正是Task存在的一个重要原因。有的Activity,虽然不在同一个App中,但为了保持用户操作的连贯性,把他们放在同一个任务中。例如,在我们的应用中的一个Activity A中点击发送邮件,会启动邮件程序的一个Activity B来发送邮件,这两个Activity 是存在于不同App中的,但是被系统放在一个任务中,这样当发送完邮件后,用户按Back键返回,可以返回到原来的Activity A中;再比如微信分享,从一个APP调用微信分享会跳转到微信界面,当微信分享完毕后会返回原来的App界面,正式通过Task才保证了良好的用户体验。
言归正传,来看这四种LaunchMode下Activity的具体行为。
1.standard
这是Activity默认的启动模式,也是最简单的启动模式,standard模式允许在一个Task中拥有多个Activity的实例。如果我们多次启动同一个Activity,那么每次都会重新生成一个该Activity的实例,并放置在该Task的顶部。当按Back键时,会一个一个地将该Activity的实例出栈。如A->A->A……(A表示一个Activity的实例)。
2.singleTop
如果一个以singleTop模式启动的Activity的实例已经存在于任务栈的栈顶,那么再启动这个Activity时,将不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法,将Intent对象传递到这个实例中。如果以singleTop模式启动的Activity的一个实例已经存在于任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会再次创建一个实例,按下Back键时,也会依次出栈。
3.singleTask
官方文档说明如下:
The system creates the activity at the root of a new task and routes the intent to it.
However, if an instance of the activity already exists,
the system routes the intent to existing instance through a call to its onNewIntent()method, rather than creating a new one.

简单来说就是在启动一个singleTask的Activity实例时,如果系统中已经存在这样一个实例,就会将这个实例调度到任务栈的栈顶,并清除它当前所在任务中位于它上面的所有Activity。注意的是该Task中并不是永远只有这个标记为singleTask的Activity,也可以有其他Activity。这只是表面现象,其实我们忽视了一个很重要的属性:taskAffinity。
如从ActivityA跳转ActivityB:
A的taskAffinity如果在不设置的情况下默认是包名,B的taskAffinity如果设置为com.launchmode.b(假设跟包名不同)。当A启动B时,如果B的启动模式为“singleTask”,framework会将它的启动标志设为FLAG_ACTIVITY_NEW_TASK。由于B的taskAffinity是com.launchmode.b,那么framework会检索是否已经存在了一个taskAffinity为com.launchmode.b的任务栈。
(1)如果存在taskAffinity相同的任务栈,则检查在这个任务栈中是否已经有了一个B实例,如果已经存在一个B实例,则会重用这个任务栈和任务栈中的B实例,将这个任务栈调到前台,清除位于B上面的所有Activity,显示B Activity,并调用B的onNewIntent();如果不存在B的实例,会在这个任务栈中创建B的实例,并调用onCreate()方法。
(2)如果不存在taskAffinity相同的任务栈,则会创建一个新的taskAffinity为com.launchmode.b
的任务栈,并且将B在这个新的任务栈中启动。
4.singleInstance
官方文档说明如下:
Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance.
The activity is always the single and only member of its task.
【Activity四种LaunchMode详解】以singleInstance模式启动Activiyt时,如果已经存在了一个实例(该任务中只有这一个Activity实例),那么会把它所在的任务栈调度到前台,重用这个实例。如果不存在,会开启一个新任务栈,并在这个新任务栈中启动这个singleInstance模式的Activity的一个实例。注意的是该Task中永远只有这一个标记为singleInstance的Activity,它是该Task的唯一成员,不可以有其他Activity。

    推荐阅读