Activity 启动模式

来源:互联网 发布:数据库完整性约束类型 编辑:程序博客网 时间:2024/06/05 05:17

  • Flag
    • FLAG_ACTIVITY_NEW_DOCUMENT
    • FLAG_ACTIVITY_MULTIPLE_TASK
    • FLAG_ACTIVITY_RETAIN_IN_RECENTS


Flag

FLAG_ACTIVITY_NEW_DOCUMENT

此处document 这个单词实在是不知道怎么翻译才恰当,document 本意就是文档,文件的意思,本文展示就翻译成文档的意思吧,我觉得这样稍微准确一点,因为更具google 官方文档对此flag 的解释以及相关的举例说明中,我觉得用文档可能更好一点,

在说FLAG_ACTIVITY_NEW_DOCUMENT 之前我们想来回想一下我们在pc端某系程序的一种场景,在使用pc 的时候,比如邮件客户端,当我们在阅读邮件某一封邮件的时候,突然需要查看之前的某一封邮件,这时候我们往往不是关掉当前邮件,再去打开另一封有邮件,查看完了后再打开之前关闭的邮件继续查阅。而是在当前邮件窗口打开的同事,在新建一个窗口打开我们需要查看的之前的邮件,这样就可以不用关闭当前的邮件窗口,实现两个邮件窗口同时打开,在查阅过程中随时都可以再窗口之间切换,是不是很方便?这好像是理所当然,pc 上大家都已经习惯了很多很多应用可以同时打开多个窗口,比如office 办公软件,还有浏览器等等,并且通过快捷键或者鼠标很方便再各个窗口之间切换,可是在移动平台android 手机上呢?

大家都知道在android 手机上一般都有3个按键(虚拟的或者物理的)返回键,home 键,recent 键,当我们按下recent 键的时候,手机会启动一个叫 Recents Screen的东西,在 Recents Screen 界面可以实现在之前打开过的app 之间快速切换,之所以能这样是因为android 有一种叫做Task 的机制,默认情况情况下,每次新启动一个app 的时候都会新建一个task,之后启动的App 内的activity 都放入同一个task,也就是说默认情况下不同app 都有不同的task,所以通过recent 在不同task 之间切换就实现了不同app的切换。

既然recent 按键可以实现不同task 之间的切换,那么我们是不是可以在启动App 内的每一个Activity 的时候给每一个Intent add一个 FLAG_ACTIVITY_NEW_TASK 同时在AndroidManifest.xml 文件中为每一个Activity 设置不同的android:taskAffinity,这样每一个Activity 都属于不同的task,就可以通过recent 见来切换了,咋一看貌似是这样,如果这样就能实现了那么FLAG_ACTIVITY_NEW_DOCUMENT 就没必要登场了,通过 FLAG_ACTIVITY_NEW_TASK 和android:taskAffinity 的确是可以让每一个Activity 在单独的task里面,正因为这样所以该activity始终只能存在一个instance,当activity 存在的时候再次启动只会让其进入到前台(from background comes to the foreground ).也就是说虽然可以方便的App 内的不同Activity 之间切换,但是每一个Activity 在没有被finish 之间只能存在一个instance,所以要让一个用来显示email 详情的DetailActivity 同时存在多个instance 来显示多个email是不可能的。因此FLAG_ACTIVITY_NEW_DOCUMENT 派上用场了,

FLAG_ACTIVITY_NEW_DOCUMENT 的作用就是让通过该intent启动的activity 在启动的时候新建一个task,该activity 作为这个task的 root activity,下面有一张android 官网的图片:这里写图片描述

The Recents screen showing three Google Drive documents, each represented as a separate task.

图片显示的是一款google 的app,正如图片显示的那样,可以通过Recent 按键在app 内的不同Activity 之间切换,虽然它们属于同一个App,但是他们存在不同的task 里面。所以可以通过Recent 按键在不同task 之间切换,

如果仅仅只是单独使用FLAG_ACTIVITY_NEW_DOCUMENT (不和FLAG_ACTIVITY_MULTIPLE_TASK一起)其特性和FLAG_ACTIVITY_NEW_TASK 一样的效果,也即是说activity 只能有一个instance,如果要实现我们所希望的效果:比如邮件客户端的DetailActivity,可以同时启动多个DetailActivity 的instance,每一个instance 打开的是不同的邮件,并且还能通过Recent 按键在不同邮件之间切换,要实现这种效果就要和FLAG_ACTIVITY_MULTIPLE_TASK 一起使用,这样每次startIntent(Intent)的时候都创建新的task。

使用了FLAG_ACTIVITY_NEW_DOCUMENT和 FLAG_ACTIVITY_NEW_TASK 还有一点不一样,FLAG_ACTIVITY_NEW_TASK 的activity在finish掉后,在Recent Screen 中还能看见,而FLAG_ACTIVITY_NEW_DOCUMENT的activity在finish 后将会被 remove 掉。为了不被remove 掉,可以和 FLAG_ACTIVITY_RETAIN_IN_RECENTS一起使用。

如果要在app 的不同地方启动同一个document activity 每次都要在代码中设置FLAG_ACTIVITY_NEW_DOCUMENT,android 提供了一种更好的方式,在 AndroidManifest.xml 中的 activity 中 设置documentLaunchMode属性。documentLaunchMode属性 有4个value:

  • always: 和FLAG_ACTIVITY_NEW_DOCUMENT 与FLAG_ACTIVITY_MULTIPLE_TASK 一起使用效果一样。一但activity documentLaunchMode 设置了该属性,不管 启动activity 的intent 是否设置了FLAG_ACTIVITY_NEW_DOCUMENT 与FLAG_ACTIVITY_MULTIPLE_TASK 中的一个还或者2个,或者一个都不设置,启东市每次都要创建新的task。
  • intoExisting:和设置FLAG_ACTIVITY_NEW_DOCUMENT 不设置FLAG_ACTIVITY_MULTIPLE_TASK 一起使用效果一样,如果启动的task 存在就不会创建,(注:android文档上说: If such a task is found that task will be cleared and restarted with the root activity receiving a call to Activity.onNewIntent. 如果task 被找到,那么task 将会被cleared,并且root activity onNewIntent 方法将会被调用,但是实际上我再api21,api25,api26 的模拟器上测试都没有发现这种现象,反而仅仅只是把存在的task , bring to foreground)。但是如果FLAG_ACTIVITY_NEW_DOCUMENT 与FLAG_ACTIVITY_MULTIPLE_TASK 一起使用,那么 intoExisting就没有效果,启动时仍然每次都创建新的task。
  • never: 这个属性值在我时间测试过程中发现也和官方文档说的不一样,官方说:This activity will not be launched into a new document even if the Intent contains Intent.FLAG_ACTIVITY_NEW_DOCUMENT. This gives the activity writer ultimate control over how their activity is used. 意思说如果设置了该属性,即使intent 设置了FLAG_ACTIVITY_NEW_DOCUMENT,也没用。但是实际测试过程中发现,如果Intent 中包含了FLAG_ACTIVITY_NEW_DOCUMENT即使documentLaunchMode = “never” 也没用,仍然会启动一个新task,但是会对FLAG_ACTIVITY_MULTIPLE_TASK有影响,FLAG_ACTIVITY_MULTIPLE_TASK将会被忽略,
  • none:默认属性。

注意:always 和 intoExisting 设置的activity launchMode 必须是standard ,否则效果就冲突了


FLAG_ACTIVITY_MULTIPLE_TASK

这个FLAG 一般都不单独使用,通常和FLAG_ACTIVITY_NEW_DOCUMENT,FLAG_ACTIVITY_NEW_TASK等一起结合使用,但是最好不要和FLAG_ACTIVITY_NEW_TASK一起使用,因为和FLAG_ACTIVITY_NEW_TASK一起使用每次新建task 后,之前的task 在Recent Screen 里面就找不到了,但是之前task 里面的activity 都还存在,没有被finish 掉,只是我们看不到了,这点可以通过log 日志输出activity 的onCreate,onDestroy 的方式来证明,常规途径我们虽然看不到,但是我们可以通过 adb shell dumpsys activity 命令看一查看到 之前的task 的确存在。要一起使用也可以,除非你自己实了top-level application launcher 或者提供了能够返回之前启动过的task 的方式。

FLAG_ACTIVITY_NEW_DOCUMENT 单独使用的时候,每次创建task之间都会去寻找是否有已经存在的task 能够匹配当前的intent,如果已经存在则把 存在的task bring to foreground,不存在则创建一个新的,如果和FLAG_ACTIVITY_MULTIPLE_TASK一起使用,这不会去寻找,每次都创建新的。


FLAG_ACTIVITY_RETAIN_IN_RECENTS

通过FLAG_ACTIVITY_NEW_DOCUMENT 启动的task ,当root activity 被关闭(finish)后,默认情况下 该task 的记录将不会在 recents(Recent screen中) 中保留,为了能在recents 里面被保留,就需要和 FLAG_ACTIVITY_RETAIN_IN_RECENTS一起搭配使用。
如果设置 activity 的 autoRemoveFromRecents 属性 或者在关闭activity的时候 explcitly calling Activity.finishAndRemoveTask(),那么FLAG_ACTIVITY_RETAIN_IN_RECENTS将会被覆盖而不起作用,

原创粉丝点击