本文主要分析Activity的启动模式及使用场景。
一、Activity启动模式浅析
1、standard
标准模式,系统默认的启动模式。在启动Activity时,系统总是创建一个新的Activity实例。其缺点是:复用性差、占用内存,当Activity已经在栈顶时,还是会创建实例。
2、singleTop
这种模式可以实现栈顶复用的效果。
如果目标Activity已经存在于栈顶,则调用实例的 onNewIntent,否则创建一个新的实例,可以用于通知启动的内容显示,例如新闻客户端的内容页面。信息类应用的列表Activity往往也会使用这种启动模式,例如,收到新短信时,如果信息列表Activity已经在栈顶了,则直接调用其onNewIntent,而不需要创建新的Activity。
该模式下,当Activity不在栈顶时,还是会创建新的实例。例如A、B、C三个Activity处于一个任务栈中,且C在栈顶,如果C启动A,则会创建一个新的实例并置于栈顶,使得当前任务栈有两个A实例。
3、singleTask
该模式实现栈内复用的效果。如果栈内已经有目标Activity实例,则清除目标Activity上面的所有Activity、使得目标Activity直接放到栈顶,并调用目标Activity的onNewIntent方法;否则创建一个新的Activity实例。
补充,该模式Activity会在跟它有相同taskAffinity的任务中启动,并且位于这个任务的堆栈顶端,这样如果我们没有设置taskAffinity,从本应用启动的Activity就会复用当前Task,也就不会创建一个新的Task。
该启动模式,适合作为程序入口点,例如原生Launcher以及相机应用中的CameraActivity,就是使用了这种启动模式。
4、singleInstance
系统级的复用。启动Activity时,如果系统中不存在该Activity实例,则创建一个新的ActivityTask,并且独占这个Task,否则显示已有的Activity实例。通常用于系统级的应用,在整个系统中只有一个实例,例如来电提醒、闹钟提醒。
这四种启动模式创建一个新Activity实例的几率,是依次降低的。实际在使用时,往往会用到动态设置启动模式,给Intent设置特定的Flag,例如FLAG_ACTIVITY_SINGLE_TOP(对应singleTop)、FLAG_ACTIVITY_NEW_TASK(对应singleTask)。
二、使用中的注意事项
首先要注意Flag的动态设置方式,优先级高于静态方式(通过AndroidManifest.xml设置)。如果这两种设置方式混合在一起,则Activity启动过程、最终效果要分为多种情况来考虑。
其次,从非Activity组件例如Service启动Activity时,必须添加FLAG_ACTIVITY_NEW_TASK这个Flag。可以思考下,系统这样设计的原因?
再次,由于部分启动模式在启动Activity时,有时候并不会重新创建一个实例,也就不会调用其onCreate方法,而是回调onNewIntent方法,如果在启动时需要根据Intent重新加载数据,注意在onNewIntent中添加对应的处理。由于Activity在某些情况下,可能会被系统销毁,为了保险,Intent获取数据的处理,最好在onCreate、onNewIntent这两个函数中都做添加。
最后,如果我们用了FLAG_ACTIVITY_CLEAR_TOP这个flag启动Activity,当栈内已有目标Activity实例时,系统的处理会分为两种情况:
a. 只设置了FLAG_ACTIVITY_CLEAR_TOP,系统会销毁目标Activity和它之上的所有Activity,重新创建目标Activity,并不调用其onNewIntent方法。
b. 设置了FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_SINGLE_TOP,系统只销毁之上的所有Activity,复用目标Activity,调用onNewIntent方法,效果相当于设置FLAG_ACTIVITY_NEW_TASK,也就是singleTask模式。
补充,适合使用singleInstance启动模式的Activity,基本都具有高优先级、业务逻辑的交互相对简单,也就是与其他应用的交互场景不多。而singleTask模式更适用于那些具有一定频度的交互场景的Activity,例如图库、联系人、一些第三方App问问需要启动相机拍照,然后再返回,这时候如果使用singleInstance则会始终独占一个任务栈,体验不好。换句话说,启动模式的设计,本质就是为了优化窗口返回的层次关系,改善用户体验。这其中又涉及到了Android任务栈模型,在后面文章继续分析。
(相关完整且成体系的文章可参见本人原创的开源电子书《Android系统与性能优化》,地址:https://github.com/carylake/androidnotes)