Android系统中的Activity可以说一件很赞的设计,它在内存管理上良好的设计,使得多任务管理在Android系统中运行游刃有余。但是Activity绝非启动展示在屏幕而已,其启动方式也大有学问,本文讲具体介绍Activity的启动模式的诸多细节,纠正一些开发中可能错误的观点,帮助大家深入理解Activity。
行文之前在正式行文之前,先介绍一些文章提到的概念
文章后续会提到Task,这里的Task指的是与用户交互的Activity实例的集合。
Task中的Activity实例以栈的形式存放,这个栈就是Activity的回退栈。
本文图片较多,在看图时,请注意观察Activity顶部的title,来区分具体Activity。
为何有启动模式应用中的每一个Activity都是进行不同的事物处理。以邮件客户端为例,InboxActivity目的就是为了展示收件箱,这个Activity不建议创建成多个实例。而ComposeMailActivity则是用来撰写邮件,可以实例化多个此Activity对象。合理地设计Activity对象是否使用已有的实例还是多次创建,会使得交互设计更加良好,也能避免很多问题。至于想要达到前面的目标,就需要使用今天的Activity启动模式。
如何使用使用很简单,只需要在manifest中对应的Activity元素加入android:launchMode属性即可。如下述代码
1
2
3
4
5
<activity
android:name=".SingleTaskActivity"
android:label="singleTask launchMode"
android:launchMode="singleTask">
</activity>
接下来就是介绍launchMode的四个值的时刻了。
standard这是launchMode的默认值,Activity不包含android:launchMode或者显示设置为standard的Activity就会使用这种模式。
一旦设置成这个值,每当有一次Intent请求,就会创建一个新的Activity实例。举个例子,如果有10个撰写邮件的Intent,那么就会创建10个ComposeMailActivity的实例来处理这些Intent。结果很明显,这种模式会创建某个Activity的多个实例。
Android 5.0之前的表现这种Activity新生成的实例会放入发送Intent的Task的栈的顶部。下图为启动同一程序内的Activity。
下面的图片展示跨程序之间调用,新生成的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序。
但是当我们打开任务管理器,则会有一点奇怪,应为显示的任务是Gallery,展示的界面确实另一个程序的Activity(因为其位于Task的栈顶)。
这时候如果我们从Gallery应用切换到拨号应用,再返回到Gallery,看到的还是这个非Gallery的Activity,如果我们想要对Gallery进行操作,必须按Back键返回到Gallery界面才可以。确实有点不太合理。
Android 5.0及之后表现对于同一应用内部Activity启动和5.0之前表现一样,变化的就是不同应用之间Activity启动变得合理了。
跨应用之间启动Activity,会创建一个新的Task,新生成的Activity就会放入刚创建的Task中。如下图
同时任务管理器查看任务也显得更加合理了。
假设之前存在我们的测试程序,然后从Gallery又分享文件到我们的测试程序,则对应的任务管理器展示效果如下。
使用场景:standard这种启动模式适合于撰写邮件Activity或者社交网络消息发布Activity。如果你想为每一个intent创建一个Activity处理,那么就是用standard这种模式。
singleTopsingleTop其实和standard几乎一样,使用singleTop的Activity也可以创建很多个实例。唯一不同的就是,如果调用的目标Activity已经位于调用者的Task的栈顶,则不创建新实例,而是使用当前的这个Activity实例,并调用这个实例的onNewIntent方法。
在singleTop这种模式下,我们需要处理应用这个模式的Activity的onCreate和onNewIntent两个方法,确保逻辑正常。 使用场景