Activity launchMode,taskAffinity,Intent.Flag

来源:互联网 发布:sql中delete和drop 编辑:程序博客网 时间:2024/05/16 14:03

参考:
1. www.programering.com
2. http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
3. developer.android.com


1. Task 和 返回栈

Android中用Task来表示完成一项任务的Activity集合。这些Activity随着访问的顺序被压入到栈中,通过按返回键可以回退到之前的Activity。用户按下HOME键,点开一个Application,一个task就创建并且后续的Activity被进栈保存。这里面包括俩层栈结构,返回栈和task中的activity栈。返回栈中可以放入多个task,一个task中可以放入多个Activity。

注意:这里有一个很重要的概念,taskroot activitytask的名字由root activity的affinitask决定,task在被系统回收的时候,也只保存root activity的状态

以task为单位,压入栈;返回的时候,按照Activity为单位,此顶向下返回;
返回栈
某些activity可能会开启一些新的task, 新task会叠加到返回栈中。
这里写图片描述
甚至在SingleTask模式下,启动一个已经在其它Task中存在的Activity,该Activity所在的task会整体压入返回栈。用户点击返回,会依次返回task #2 -> task #1
这里写图片描述


2. taskAffinity

taskAffinity 标示以该Activity为root的所在task的名字。属性值推荐用.开头。
可以通过<application>给所有activity设置taskAffinity。

<application   taskAffinity=".newtask" >   <activity *** />    ***</application>

也可以单独设置activity 的taskAffinity

<activity taskAffinity=".newtask"/>

如果<application><acitivity>都没有设置taskAffinity,则系统默认赋值为应用程序包名。也就是说taskAffinity要么是自己定义的值,要么去应用程序包名。
值得注意的是,如果launcher activity使用默认taskAffinity,通过launcher activity启动的一个activity B,B配置了taskAffinity属性,并且没有设置启动新的task, 那么其实B的taskAffinity就失效了,因为task的名字是由root activity的taskAffinity决定的。

3. launchMode

Android <activity> 节点下的属性launchMode 用来控制Activity的启动方式。可取四种值:

  • standard
  • singleTop
  • singleTask
  • singleInstance

1.standard

standard 模式是,每次通过intent启动activity的时候都会在当前Task中创建一个Activity实例,并放到栈顶。如果不申名launchMode,系统默认是standard,这种方式适合大部分业务型Activity,比如查看,浏览等等

stardard 模式,图片来自(http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en)

2.singleTop

singleTop 模式下,每次启动一个新的singleTop Activity的时候, 都会在当前task栈栈顶去寻找此Activity的实例,如果存在,则不重新创建,反而调用此ActivityonNewIntent()方法、反之,重新创建。所以在这种模式下,不要忘记在onCreate()onNewIntent()同时处理Intent data

singleTop 模式,图片来自(http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en)


3.singleTask

singleTask 模式比较特殊,并不是完全如官网所说的

The system creates a new task and instantiates the activity at the root of the new task.
“系统会创建一个新的Task,同时实例化Activity,并把它放到新Task的栈底”

启动activity的时候,系统寻找名为该ActivitytaskAffinity的task,如果有找到,清除该task该activity上面所有的Activity,并调用onNewIntent()方法。如果没有找到,则创建该ActivitytaskAffinity为名的task,并放入栈底作为root。在此acitivity上启动的Activity,如果没有特殊配置,则默认是在该task中。

singleTask模式旨在保证以该taskAffinity为名的task是唯一的。


4.singleInstance

singleInstance用到的情况比较少,他允许一个Activity独占一个task,启动这种activity的时候,会在所有栈中寻找实例,如果找到,调用onNewIntent(),没有找到则创建task,并实例化Activity放入其中。

需要注意的是,如果在SingleInstance Activity中启动普通Activity ,会通过普通Activity的 taskAffinity寻找task, 并放入栈顶,没有找到则创建task。


4. allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch

Android 系统把完成任务的activity放入task当中,多个task意味着系统保存着多个任务状态。同一时刻用户其实仅仅和一个task交互。这个时候,保存过多的task会耗掉部分系统资源。为了不影响用户体验,同时及时回收资源,Android 系统在用户退出task一段时间后自动销毁每个activity,但保存且只保存每一个task的root Activity的状态。 但是用户可以通过Activity的manifest来调配系统的这种默认行为。

  • allowTaskReparenting 设置为true的时候,允许activity转移task。例如邮件app有一个链接打开网页,网页activity此时属于email-task。如果配置了allowTaskReparenting,则打开浏览器app的时候,网页activity就会迁移到brownser-task。
  • clearTaskOnLaunch 设置为true的时候,只要退出task, 系统立即回收task,只保存root activity状态
  • alwaysRetainTaskState 设置为true的时候,系统在回收task的时候,保存所有Activity的状态
  • finishOnTaskLaunch 这个属性只针对当前Activity,设置为true的时候,task在被加载的时候,该Activity会被自动清除


5. Intent.FLAG_ACTIVITY_XXX

除了使用manifest 文件来配置Activity的启动模式,还可以通过代码动态指定要启动的Activity的启动方式,通过startActivity传入带启动标志的Intent。这种方式相较于launchMode的主动宣称,更加具有灵活性。但是二者并不是一一对应的逻辑,而是针对不同场景配合使用。
Intent的acitivity flag比较多,这里仅仅介绍几种常用的,并且标出Google留给我们的坑。

  • FLAG_ACTIVITY_NEW_TASK
    这里注意,并不是google官方说的:

    This produces the same behavior as the “singleTask” launchMode value
    “标记它的行为就和launchMode=’singleTask’行为一样”

    配合FLAG_ACTIVITY_CLEAR_TOP的时候,才会和“singleTask”行为一致–在已经存在目标activity的情况下,清除上层全部Activity.

  • FLAG_ACTIVITY_SINGLE_TOP
    单独使用它能达到launchMode=”singleTop”的效果

  • FLAG_ACTIVITY_CLEAR_TOP
    启动Activity传入此标志,会使得activity在task中上层的activity全部清除。通常是和singleTop模式或者FLAG_ACTIVIATY_NEW_TASK一起使用。
    配合singleTop模式的时候,会避免重新创建Activity,同时清除前面所有的activity(其实效果就是已经存在目标Activity的singleTask)
    配合FLAG_ACTIVITY_NEW_TASK能达到singleTask效果


0 0
原创粉丝点击