Intent中关于Activity的Flag

Author Avatar
罗炜光 7月 12, 2016
  • 在其它设备中阅读本文章

launchMode启动时默认的Flag

  • standard 为0,即无Flag
  • singleTop 为0,即无Flag
  • singleTask 为0x10000000,即FLAG_ACTIVITY_NEW_TASK
  • singleInstance 为0x10000000,即FLAG_ACTIVITY_NEW_TASK

Flag详解

FLAG_ACTIVITY_BROUGHT_TO_FRONT

默认标志

This flag is not normally set by application code, but set for you by the system as described in the launchMode documentation for the singleTask mode.

通常在应用代码中不需要设置这个FLAG,当launchMode为singleTask时系统会默认设置这个标志。

然而在实际的测试中并没有测试出,而是在另外两种方式设置了此标志

  1. 当从launchMode为singleInstance的Activity跳转到standard、singleTop和singleTask的
  2. 当安装或更新一个app后有两个选项,一个为完成一个为打开,点击打开,不管跳多少个Activity,按Home键再从点击桌面图标进入,都会加载一个新的启动的Activity,而不是刚刚执行的,此时的Activity也设有此标志

解决此问题的方法

if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0)
{
    finish();
    return;
}

FLAG_ACTIVITY_CLEAR_TASK

清空任务标志

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.

如果Intent中设置了这个标志,会导致含有待启动Activity的Task在Activity被启动前清空。也就是说,这个Activity会成为一个新的root,并且所有旧的activity都被finish掉。这个标志只能与FLAG_ACTIVITY_NEW_TASK 一起使用。

standard与singleTop设置此Flag的同时还要设置FLAG_ACTIVITY_NEW_TASK才有效,而singleTask启动时默认会有FLAG_ACTIVITY_NEW_TASK,所以只要添加此Flag即可,而singleInstance因为新建了个Task,所以设置不设置效果一样

FLAG_ACTIVITY_CLEAR_TOP

清空任务中在其之上的Activity

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.

The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be “multiple” (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance’s onNewIntent().

This launch mode can also be used to good effect in conjunction with FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task, it will bring any currently running instance of that task to the foreground, and then clear it to its root state. This is especially useful, for example, when launching an activity from the notification manager.

See Tasks and Back Stack for more information about tasks.

如果设置了这个标志,并且待启动的Activity已经存在于当前的task中,那就不会再给这个activity新起一个实例,而是将task中在它之上的其它activity全部关闭,然后把Intent作为一个新的Intent传给这个Activity(当前已在栈顶)。

例如,一个task中存在A,B,C,D四个Activity。如果D调用startActivity() 启动B,那么C和D会被finish掉并且B收到这个Intent,最后栈中只有A,B。

上面例子中运行的B activity既可以在onNewIntent()中接收新的Intent,也可以将自己finish掉然后使用新的Intent重启。如果在它的launch mode中设置了”multiple”(默认),并且intent中没有设置 FLAG_ACTIVITY_SINGLE_TOP 标志,那它就会被finish掉然后重新创建。如果是其它的launchMode或者是设置了FLAG_ACTIVITY_SINGLE_TOP 属性,那就会使用现有的实例的OnNewIntent()方法来接受Intent。

这种启动模式也可以与 FLAG_ACTIVITY_NEW_TASK 一起使用:如果用来启动一个任务的root activity,它会将这个任务中现在运行的实例调到前台,然后将任务清空至只有根Activity的状态。这很有用,例如要从通知中心里启动一个Activity时。

总结:

  1. 如果launchMode为standard,且为设置FLAG_ACTIVITY_SINGLE_TOP,则使用此标记打开Activity时,假如栈内已存在此Activity,那么会将栈中此Activity之上包括本身全部销毁,并创建此Activity,如果设置FLAG_ACTIVITY_SINGLE_TOP则与launchMode为singleTop相同
  2. 如果launchMode为singleTop,则使用此标记打开Activity时,假如栈内已存在此Activity,那么会将栈中此Activity之上(但不包括本身)全部销毁,调用onNewIntent(),并恢复此Activity
  3. 如果launchMode为singleTask,则无影响,因为 singleTask本身就是以此方式进行处理
  4. 如果launchMode为singleInstance,无影响

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET(已废弃)

任务重置时将任务中在此标记之后的Activity清空

If set, this marks a point in the task’s activity stack that should be cleared when the task is reset. That is, the next time the task is brought to the foreground with FLAG_ACTIVITY_RESET_TASK_IF_NEEDED (typically as a result of the user re-launching it from home), this activity and all on top of it will be finished so that the user does not return to them, but instead returns to whatever activity preceeded it.

This is useful for cases where you have a logical break in your application. For example, an e-mail application may have a command to view an attachment, which launches an image view activity to display it. This activity should be part of the e-mail application’s task, since it is a part of the task the user is involved in. However, if the user leaves that task, and later selects the e-mail app from home, we may like them to return to the conversation they were viewing, not the picture attachment, since that is confusing. By setting this flag when launching the image viewer, that viewer and any activities it starts will be removed the next time the user returns to mail.

设置这个标志意味着在activity栈中做一个标记,在Task重置的时候栈就把从标记往上的activity都清除。也就是说,下次这个Task被通过FLAG_ACTIVITY_RESET_TASK_IF_NEEDED调到前台时(通常是由于用户从桌面重新启动),这个activity和它之上的activity都会被finish掉,这样用户就不会再回到他们,而是直接回到在它们之前的activity。

这在应用切换时非常有用。比如,Email应用会需要查看附件,就要调用查看图片的Activity来显示,那这个查看图片的Activity就会成为Email应用任务里的一部分。但是,如果用户离开了Email的任务,过了一会儿由通过Home来选择Email应用,我们会希望它回到查看邮件会话的页面,而不是浏览图片附件的页面,不然就感觉太诡异了。如果在启动查看图片Activity时设置了这个标志,那这个Activity及由它启动的Activity在下一次用户返回邮件时都会被清除。

已经废弃,请使用FLAG_ACTIVITY_NEW_DOCUMENT

当LaunchMode为standard或singleTop此标记在5.0之前与5.0之后有很大差别

  • 5.0之后使用此标志后,会新建一个task,并且后续的Activity都会在此task中,而在overview screen中(总览画面或者叫最近画面,最近任务表)中可以看到有两个
  • 5.0之前都在一个task中

此标记对singleTask无效

此标记对于singleInstance有效,但5.0后在overview screen中不会产生两个

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

不显示在近期任务中

If set, the new activity is not kept in the list of recently launched activities.

如果设置这个标志,这个Activity就不会在近期任务中显示。
等同于android:excludeFromRecents=”true”
但似乎没效果?

FLAG_ACTIVITY_FORWARD_RESULT

转发结果

If set and this intent is being used to launch a new activity from an existing one, then the reply target of the existing activity will be transfered to the new activity. This way the new activity can call setResult(int) and have that result sent back to the reply target of the original activity.

如果Activity A 在启动 Activity B时设置了这个标志,那A的答复目标目标会传递给B,这样一来B就可以通过调用setResult(int) 将返回结果返回给A的答复目标。

简单如下:

O —-startActivityForResult()—-> A —-FLAG_ACTIVITY_FORWARD_RESULT—-> B

A的答复目标是O,如果A在启动B时使用了这个标志,A就会把答复目标O的信息传递给B,以便B将O作为它的答复目标。此时B调用setResult()时的结果信息都会传递给O,而不会给A。并且此时在A中调用setResult()的内容不会生效。我还没发现使A中setResult()生效的方法。

注意:这个标志不能与startActivityForResult()一起使用。

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

从近期任务中启动的标志

This flag is not normally set by application code, but set for you by the system if this activity is being launched from history (longpress home key).

这个标志通常情况下不会通过应用的代码来设置,而是在通过最近任务启动activity时由系统设置的。

FLAG_ACTIVITY_MULTIPLE_TASK

Activity可在多任务运行的标志

Do not use this flag unless you are implementing your own top-level application launcher. Used in conjunction with FLAG_ACTIVITY_NEW_TASK to disable the behavior of bringing an existing task to the foreground. When set, a new task is always started to host the Activity for the Intent, regardless of whether there is already an existing task running the same thing.

Because the default system does not include graphical task management, you should not use this flag unless you provide some way for a user to return back to the tasks you have launched.

This flag is ignored if FLAG_ACTIVITY_NEW_TASK is not set.

See Tasks and Back Stack for more information about tasks.

除非你实现了自己的顶级应用启动器,否则不要使用这个标志。与 FLAG_ACTIVITY_NEW_TASK 一起使用可以不再把已存在的任务唤起到前台。 当被设置时,系统总会为Intent的Activity启动一个新的task,而不管是否已经有已存在的任务在做同样的事情。

因为默认系统不包含图形化的任务管理功能,所以除非你给用户提供了返回到已启动任务的方法,否则就不要用这个标志。

如果FLAG_ACTIVITY_NEW_TASK没有设置,则这个标志也被忽略。

FLAG_ACTIVITY_NEW_DOCUMENT

api 21之后加入的一个标识,用来在intent启动的activity的task栈中打开一个document,和documentLaunchMode效果相等,有着不同的documents的activity的多个实例,将会出现在最近的task列表中。单独使用效果和documentLaunchMode=”intoExisting”一样,如果和FLAG_ACTIVITY_MULTIPLE_TASK一起使用效果就等同于documentLaunchMode=”always”

FLAG_ACTIVITY_NEW_TASK

尝试在新任务中启动Activity的标志(并不一定就会在新的任务中)

If set, this activity will become the start of a new task on this history stack. A task (from the activity that started it to the next task activity) defines an atomic group of activities that the user can move to. Tasks can be moved to the foreground and background; all of the activities inside of a particular task always remain in the same order. See Tasks and Back Stack for more information about tasks.

This flag is generally used by activities that want to present a “launcher” style behavior: they give the user a list of separate things that can be done, which otherwise run completely independently of the activity launching them.

When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in. See FLAG_ACTIVITY_MULTIPLE_TASK for a flag to disable this behavior.

This flag can not be used when the caller is requesting a result from the activity being launched.

设置这个标志可以为待启动的Activity创建一个新的任务。一个任务(从启动它的Activity到任务中的下一个Activity)就是用户可以跳转到的Activity的原子群。任务可以在前台与后台之间切换;在某一特定任务之中的所有Activity一直会保持同样的顺序。

这个标志通常被用来呈现一种”laucher”类型的行为:为用户提供一个可单独解决的事情列表,完全独立于启动他们的Activity之外运行。

使用这个标志时,如果有一个任务已经运行了你要启动的Activity,那就不会在创建新的Activity,而是将现有的任务保持之前的状态直接唤到前台。参见FLAG_ACTIVITY_MULTIPLE_TASK这个标志,可以禁用掉这个行为。

这个标志不能在调用者向待启动Activity请求返回结果时使用。

注意:假设A启动B,如果要让B在新的task中创建,要求这两个Activity的taskAffinity不同。也就是说,设置了这个标志后,新启动的activity并非就一定在新的task中创建,如果A和B在属于同一个package,而且都是使用默认的taskAffinity,那B还是会在A的task中被创建。 所以,只有A和B的taskAffinity不同时,设置了这个标志才会使B被创建到新的task。

FLAG_ACTIVITY_NO_ANIMATION

禁用切换动画

If set in an Intent passed to Context.startActivity(), this flag will prevent the system from applying an activity transition animation to go to the next activity state. This doesn’t mean an animation will never run – if another activity change happens that doesn’t specify this flag before the activity started here is displayed, then that transition will be used. This flag can be put to good use when you are going to do a series of activity operations but the animation seen by the user shouldn’t be driven by the first activity change but rather a later one.

禁用掉系统默认的Activity切换动画。

FLAG_ACTIVITY_NO_HISTORY

不保存Activity的历史状态

If set, the new activity is not kept in the history stack. As soon as the user navigates away from it, the activity is finished. This may also be set with the noHistory attribute.

如果设置这个标志,新的Activity就不会在历史栈中保存。用户一旦离开,这个Activity就会finish掉。也可以使用noHistory属性设置。

FLAG_ACTIVITY_NO_USER_ACTION

不响应onUserLeaveHint方法

If set, this flag will prevent the normal onUserLeaveHint() callback from occurring on the current frontmost activity before it is paused as the newly-started activity is brought to the front.

Typically, an activity can rely on that callback to indicate that an explicit user action has caused their activity to be moved out of the foreground. The callback marks an appropriate point in the activity’s lifecycle for it to dismiss any notifications that it intends to display “until the user has seen them,” such as a blinking LED.

If an activity is ever started via any non-user-driven events such as phone-call receipt or an alarm handler, this flag should be passed to Context.startActivity, ensuring that the pausing activity does not think the user has acknowledged its notification.

如果设置了这个标志,可以在避免用户离开当前Activity时回调到 onUserLeaveHint(). 通常,Activity可以通过这个回调表明有明确的用户行为将当前activity切出前台。 这个回调标记了activity生命周期中的一个恰当的点,可以用来“在用户看过通知之后”将它们清除,如闪烁LED灯。

如果Activity是由非用户驱动的事件(如电话呼入或闹钟响铃)启动的,那这个标志就应该被传入Context.startActivity,以确保被打断的activity不会认为用户已经看过了通知。

FLAG_ACTIVITY_PREVIOUS_IS_TOP

If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.

如果启动Activity时设置了这个标志,那当前这个 Activity 不会被当作顶部的 Activity 来判断是否之后新Intent应该被传给栈顶Activity而不是启动一个新的Activity。之前一个的Activity会被当作栈顶,假定当前的Acitvity会立即自己finish掉。

即 A—> B —>C,若B启动C时用了这个标志位,那在启动时B并不会被当作栈顶的Activity,而是用A做栈顶来启动C。此过程中B充当一个跳转页面。

典型的场景是在应用选择页面,如果在文本中点击一个网址要跳转到浏览器,而系统中又装了不止一个浏览器应用,此时会弹出应用选择页面。在应用选择页面选择某一款浏览器启动时,就会用到这个Flag。然后应用选择页面将自己finish,以保证从浏览器返回时不会在回到选择页面。

经常与FLAG_ACTIVITY_FORWARD_RESULT 一起使用。

FLAG_ACTIVITY_REORDER_TO_FRONT

任务中的Activity顺序重排

If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought to the front of its task’s history stack if it is already running.

For example, consider a task consisting of four activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then B will be brought to the front of the history stack, with this resulting order: A, C, D, B. This flag will be ignored if FLAG_ACTIVITY_CLEAR_TOP is also specified.

如果设置了这个标志,而且被启动的Activity如果已经在运行,那这个Activity会被调到栈顶。

比如,一个任务中有4个Activity:A,B,C,D。如果D调用了startActivity() 来启动B时使用了这个标志,那B就会被调到历史栈的栈顶,结果顺序:A,C,D,B,否则顺序会是:A,B,C,D,B。 如果使用了标志 FLAG_ACTIVITY_CLEAR_TOP,那这个FLAG_ACTIVITY_REORDER_TO_FRONT标志会被忽略。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.

这个标记在以下情况下会生效:1.启动Activity时创建新的task来放置Activity实例;2.已存在的task被放置于前台。系统会根据affinity对指定的task进行重置操作,task会压入某些Activity实例或移除某些Activity实例,

FLAG_ACTIVITY_RETAIN_IN_RECENTS

pi21加入。
默认情况下通过FLAG_ACTIVITY_NEW_DOCUMENT启动的activity在关闭之后,task中的记录会相对应的删除。如果为了能够重新启动这个activity你想保留它,就可以使用者个flag,最近的记录将会保留在接口中以便用户去重新启动。接受该flag的activity可以使用autoRemoveFromRecents去复写这个request或者调用Activity.finishAndRemoveTask()方法。

FLAG_ACTIVITY_SINGLE_TOP

If set, the activity will not be launched if it is already running at the top of the history stack.

设置这个标志之后,如果被启动的Activity已经在栈顶,那它就不会被再次启动。

FLAG_ACTIVITY_TASK_ON_HOME

直接返回桌面

If set in an Intent passed to Context.startActivity(), this flag will cause a newly launching task to be placed on top of the current home activity task (if there is one). That is, pressing back from the task will always return the user to home even if that was not the last activity they saw. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.

这个标志可以将一个新启动的任务置于当前的home任务(home activity task)之上(如果有的话)。也就是说,在任务中按back键总是会回到home界面,而不是回到他们之前看到的activity。这个标志只能与FLAG_ACTIVITY_NEW_TASK标志一起用。

比如,A->B->C->D,如果在C启动D的时候设置了这个标志,那在D中按Back键则是直接回到桌面,而不是C。

注意:

只有D是在新的task中被创建时(也就是D的launchMode是singleInstance时,或者是给D指定了与C不同的taskAffinity并且加了FLAG_ACTIVITY_NEW_TASK标志时),使用 FLAG_ACTIVITY_TASK_ON_HOME标志才会生效。

感觉实际使用效果和用 FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK 的效果一样。

参考资料

Android开发——Intent中的各种FLAG
android深入解析Activity的launchMode启动模式,Intent Flag,taskAffinity