每个Activity都有不同的使用目的,比如邮箱客户端,收件箱是展示收件箱,所以这个Activity不建议创建成多个实例。而写邮件的Activity,因为我们可以同时写多封邮件, 可以实例化多个此Activity对象。设置是否使用已存在的实例还是多次创建,就需要使用Activity启动模式。
我们通过在AndroidManifest.xml 文件中的activity标签设置其android:launchMode属性来决定该Activity启动模式或者在用intent启动时Activity设置 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)相应属性。 有四种启动模式:standard, singleTop, singleTask 和 singleInstance。
重要的概念
任务:任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中。返回栈:当前 Activity 启动另一个 Activity 时,该新 Activity 会被推送到堆栈顶部,成为焦点所在。 前一个 Activity 仍保留在堆栈中,但是处于停止状态。Activity 停止时,系统会保持其用户界面的当前状态。 用户按“返回”按钮时,当前 Activity 会从堆栈顶部弹出(Activity 被销毁), 而前一个 Activity 恢复执行(恢复其 UI 的前一状态)。 堆栈中的 Activity 永远不会重新排列,仅推入和弹出堆栈: 由当前 Activity 启动时推入堆栈;用户使用“返回”按钮退出时弹出堆栈。当所有 Activity 均从堆栈中弹出后,任务即不复存在。 因此,返回栈以“后进先出”对象结构运行。
standard
这是默认的启动模式,没有设置或者android:launchMode设置为standard的Activity就会使用这种模式。设置成这个值后,每当打开Activity一次,就会创建一个新的Activity实例,比如写邮件Activity是这个启动模式, 如果你打开了10次写邮件,就会有10个Activity实例,注意,也意味着你要退出就要关掉10个Activity。
singleTop
使用singleTop的Activity,如果该Activity不在返回栈的栈顶,则创建新的实例。如果该Activity已经位于栈顶, 则不创建新实例,而是使用当前的这个Activity实例,并调用这个实例的onNewIntent方法。所以在singleTop这种模式下,我们需要处理onCreate和onNewIntent这两个方法,确保不同的情况都能正常工作。
singleTop使用例子:假设有一个搜索框,每次搜索查询都会将我们引导至SearchActivity查看结果,为了更好的交互体验, 我们在结果页顶部也放置这样的搜索框。假设一下,SearchActivity启动模式为standard, 那么每一个搜索都会创建一个新的SearchActivity实例,10次查询就是10个Activity。 当我们想要退回到非SearchActivity,我们需要按返回键10次,这会是糟糕的用户体验。
singleTask
singleTask启动模式的Activity在系统中只会存在一个实例。 如果系统中不存在Activity的实例,那么就需要创建这个Activity的实例,并且将这个实例放入栈顶。 如果Activity实例已然存在,那么在Activity回退栈中,所有位于该Activity上面的Activity实例都将被销毁掉(销毁过程会调用Activity生命周期回调),这样使得Activity实例位于栈顶。 与此同时,Intent会通过onNewIntent()传递到这个SingleTask Activity实例。该模式的使用场景多类似于邮件客户端的收件箱页面。收件箱Activity只保持一个实例即可,但是也要谨慎使用这种模式,因为它可以在用户未感知的情况下销毁掉其他Activity。
singleInstance
这个模式和singleTask差不多,因为他们在系统中都只有一份实例。 唯一不同的就是存放singleInstance Activity实例的返回栈只能存放一个该模式的Activity实例。 如果从singleInstance Activity实例启动另一个Activity,那么这个Activity实例会放入其他的返回栈中。 同理,如果singleInstance Activity被别的Activity启动,它也会放入不同于调用者的返回栈中。虽然是两个返回栈,但是在系统的任务管理器中,却始终显示一个,即最新打开的返回栈。 这样虽然返回栈1还在后台工作但是我们无法访问到他。解决这个问题的方法就是添加taskAffinity=""属性即可。这样在 任务管理器中就能看到两个返回栈。
这种模式的使用情况比较罕见,建议谨慎使用。
总结