`

android中activity设置标志FLAG_ACTIVITY_NEW_TASK,FLAG_ACTIVITY_CLEAR_TOP详解和taskAffini

 
阅读更多

 

今天解决一个比较有意思的问题

问题描述,假设有一个application中包含两个activity A和B,此时先打开A 然后按Home键退回到MainHome,在framework中回退mainHome是通过startActivity方式打开mainHome的(我们的android platform是自己定制的,对按键重新设计,可能和原生系统不一样),然后通过一个HotKey(就是一个外设的某一个按键)打开B,打开方式为StartActivity 设置两个Flag 分别是 FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK,此时奇怪的事情就发生了,当B被打开后,我们按back键回退,回退的地方竟然是A 而不是MainHome。如果我们换一种打开B的方式,不设置上面的两个Flag,那么从B就可以正常回退到MainHome,那么问题显然是出在了两个设置标志的地方上。然后翻阅文档和API。

将资料贴上:

FLAG_ACTIVITY_NEW_TASK:

一个Activity一般通过调用startActivity()启动并加入到Task中。它同调用者一样,进入同一个Task。
   然而,如果传递给startActivity()的Intent对象中包含FLAG_ACTIVITY_NEW_TASK时,系统会搜索一个新的Task来容纳新的Activity。
   通常,如标志的名字所示,是一个新的Task。然而,并不是必须是。如果已经存在一个Task与新Activity的affinity相同,这个Activity就会加入到那个Task中。如果不是,启动一个新的Task。
  如果启动它的acitve和新Activity的affinity相同,那么新Activity的会进入启动它的acitve所在的Task.

FLAG_ACTIVITY_CLEAR_TOP:

 如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。
    例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。
    上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为 “standard”(默认值),
    并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实例的onNewIntent()中。
    这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity

 

也就是说对我们上例启决定性作用的是FLAG_ACTIVITY_NEW_TASK这个flag.

原因是,当我们的打开B时,因为使用了new_task属性,所以系统就会为B寻找一个最具
affinity的activity(也就是A)如果找到了,系统会将此activity(也就是A)设置为前台状态,就是background,然后将B归并到A的Task中去,并且压入顶(如果B之前已经存在于A的Task中那么CLEAR_TOP属性将会把B之上得所有activity清除掉,然后将B压入栈顶).问题分析到这里,应该已经很清楚了,也就是说A和B一定具有相同的affinity,查阅文档发现,因为A和B存在于同一个.apk下也就是同一个package下,所以默认具有相同的affinity.下面贴上affinity的相关文档:

    什么是Affinity

在某些情况下,Android需要知道一个Activity属于哪个Task,即使它没有被启动到一个具体的Task里。这是通过任务共用性(Affinities)完成的。任务共用性(Affinities)为这个运行一个或多个Activity的Task提供了一个独特的静态名称,默认的一个活动的任务共用性(Affinity)是实现了该Activity的.apk包的名字。

 

当开始一个没有 Intent.FLAG_ACTIVITY_NEW_TASK标志的Activity时,任务共用性affinities不会影响将会运行该新活动的 Task:它总是运行在启动它的Task里。但是,如果使用了NEW_TASK标志,那么共用性(affinity)将被用来判断是否已经存在一个有相同共用性(affinity)的Task。如果是这样,这项Task将被切换到前面而新的Activity会启动于这个Task的顶层。

 

这种特性在您必须使用NEW_TASK标志的情况下最有用,尤其是从状态栏通知或桌面快捷方式启动活动时。结果是,当用户用这种方式启动您的应用程序时,它的当前Task将被切换到前台,而且想要查看的Activity被放在最上面。

 

你可以在程序清单(Manifest)文件的应用程序application标签中为.apk包中所有的活动分配你自己的任务共用性Affinites,或者在活动标记中为各个活动进行分配。

在前面的文章“Android四种Activity的加载模式”我们提到:Activity的加载模式受启动Activity的Intent对象中设置的Flag和manifest文件中Activity的<activity>元素的特性值交互控制。


跟 Task 有关的 manifest文件中Activity的特性值介绍

android:allowTaskReparenting
    用来标记Activity能否从启动的Task移动到有着affinity的Task(当这个Task进入到前台时)

  “true”,表示能移动,“false”,表示它必须呆在启动时呆在的那个Task里。

    如果这个特性没有被设定,设定到<application>元素上的allowTaskReparenting特性的值会应用到Activity上。默认值为“false”。

    一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来强制Activity移动到有着affinity的Task中。典型用法是:把一个应用程序的Activity移到另一个应用程序的主Task中。
    例如,如果 email中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序定义的,但是,现在它作为email Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当email Task再次进入前台时,就看不到它了。

   Actvity的affinity是由taskAffinity特性定义的。Task的affinity是通过读取根Activity的affinity 决定。因此,根Activity总是位于相同affinity的Task里。由于启动模式为“singleTask”和“singleInstance”的Activity只能位于Task的底部,因此,重新宿主只能限于“standard”和“singleTop”模式。

android:alwaysRetainTaskState
    用来标记Activity所在的Task的状态是否总是由系统来保持。

    “true”,表示总是;“false”,表示在某种情形下允许系统恢复Task到它的初始化状态。默认值是“false”。

    这个特性只针对Task的根Activity有意义;对其它Activity来说,忽略之。 
    一般来说,特定的情形如当用户从主画面重新选择这个Task时,系统会对这个Task进行清理(从stack中删除位于根Activity之上的所有Activivity)。典型的情况,当用户有一段时间没有访问这个Task时也会这么做,例如30分钟。
    然而,当这个特性设为“true”时,用户总是能回到这个Task的最新状态,无论他们是如何启动的。这非常有用,例如,像Browser应用程序,这里有很多的状态(例如多个打开的Tab),用户不想丢失这些状态。

       所以最终的解决方式就是为B或者A设置不同的affinity这样A 就不会被吸引到background状态了,而B 也会在另外的Task中打开。在B中按back键就会返回到MainHome界面。

分享到:
评论
1 楼 doloveme 2013-03-26  
总结:
standard  每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)
singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例 (每个Task都可以有,且可以有多个,在栈顶时可复用)
singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)
singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)


FLAG_ACTIVITY_NEW_TASK  类似singleTask
FLAG_ACTIVITY_SINGLE_TOP 类似singleTop
FLAG_ACTIVITY_CLEAR_TOP 无对应

相关推荐

    【Android开发】Activity生命周期与启动模式详解:页面跳转及Intent使用方法综述

    最后介绍了Intent标志位(FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_CLEAR_TASK、FLAG_ACTIVITY_NEW_TASK等)的作用以及显式Intent和隐式Intent的区别,还涉及了如何在Activity间传递数据和配置信息。 适合人群:具有...

    Android activity堆栈及管理实例详解

    3. `FLAG_ACTIVITY_CLEAR_TOP`:如果目标Activity已经在栈中,这个标志会清除它上面的所有Activity,然后将Intent传递给目标Activity,使其位于栈顶。 4. `FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET`:当任务被重置时,...

    Activity活动详简总结

    了解如何使用FLAG_ACTIVITY_*系列标志控制Activity的启动行为,如FLAG_ACTIVITY_NEW_TASK用于创建新的任务栈,FLAG_ACTIVITY_CLEAR_TOP用于清理栈顶到目标Activity之间的所有Activity。 最后,Activity间的通信和...

    activity

    8. **Intent Flag**:Intent的Flag可以控制Activity的行为,如FLAG_ACTIVITY_NEW_TASK用于创建新Task,FLAG_ACTIVITY_CLEAR_TOP则会清除所有位于目标Activity之上的Activity。 9. **Activity间的通信**:除了Intent...

    android intent跳转

    1. **合理使用Intent标志**:根据应用逻辑选择合适的Intent标志,例如使用`FLAG_ACTIVITY_NEW_TASK`来启动新任务栈的Activity。 2. **数据封装**:对于需要传递的数据,使用`putExtra()`方法进行封装,并确保接收端...

    Android开发指南中文版.doc

    Activity可以通过设置FLAG_ACTIVITY_NEW_TASK标志创建新的任务,或者通过FLAG_ACTIVITY_CLEAR_TOP清理任务栈。 **Affinity(吸引力)和新任务** Affinity决定了Activity所属的任务。当启动新Activity时,如果指定...

    Activity使用setContentView切换界面

    可以使用`Intent`的`FLAG_ACTIVITY_CLEAR_TOP`或`FLAG_ACTIVITY_NEW_TASK`等标志来控制返回栈的行为。 ### 3. 示例代码 下面是一个简单的界面切换示例: ```java // 在需要切换界面的Activity中 Intent intent = ...

    Android_开发指南中文版.pdf

    - 创建新任务时,可以通过设置Intent的标志`FLAG_ACTIVITY_NEW_TASK`来控制新Activity是否应该在一个新的任务中启动。 #### 加载模式 - **加载模式**定义了Activity如何加载以及在Activity栈中的行为。有多种不同...

    Android面试题集锦

    - **FLAG_ACTIVITY_CLEAR_TOP**:清除位于目标Activity之上的所有Activity,确保目标Activity位于栈顶。 - **FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET**:当任务被重置时,此Activity也将被清除。 - **FLAG_ACTIVITY...

    面试题 目 精心选择

    - `FLAG_ACTIVITY_CLEAR_TOP`:清除到目标Activity所在任务栈的顶部,使目标Activity位于栈顶。 - `FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET`:当任务被重置时清除Activity。 - `FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS...

    Android 面试题

    - **FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET**: 当用户通过系统设置将当前任务重置到初始状态时,会清除该Activity所在任务栈中的所有Activity。 - **FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS**: 将Activity从最近任务列表...

    android面试常见问题

    - **FLAG_ACTIVITY_CLEAR_TOP**: 如果Activity已经在任务堆栈中存在,则清除任务堆栈中的所有上面的Activity,使该Activity成为当前Activity。 - **FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET**: 当任务堆栈被重置时,此...

    android面试题1

    - **FLAG_ACTIVITY_NEW_TASK**: 在新任务中启动 Activity。 #### 2. Activity 和 Task 的启动模式及其含义 - **Standard**: 每次启动 Activity 时都会创建一个新的实例,即使当前 Activity 已经在任务栈中。 - **...

    安卓面试shouji

    - `FLAG_ACTIVITY_CLEAR_TOP`: 如果被启动的Activity已经在当前任务栈中,会销毁它之上的所有Activity,然后通过onNewIntent()回调。 2. **Activity与Task的启动模式** - **Standard**: 默认模式,每次启动都会...

    《intent详解(二)》源码

    Intent的FLAGs影响Intent的行为,例如FLAG_ACTIVITY_NEW_TASK表示在新的任务栈中启动Activity,FLAG_ACTIVITY_CLEAR_TOP则会清除当前任务栈中的所有Activity。 12. 深度学习 深入理解Intent的源码,可以从`...

    Android 应用程序模块 应用, 任务, 进程, 和线程--千锋培训

    Intent除了携带启动Activity的信息,还可以设置标志来影响Activity的行为,如`FLAG_ACTIVITY_NEW_TASK`和`FLAG_ACTIVITY_CLEAR_TOP`等。 6. **进程(Processes)** Android应用可以运行在不同的进程中,每个进程...

    android面试题

    - **FLAG_ACTIVITY_CLEAR_TOP**:如果启动的目标活动已经在任务栈中存在,则清除该活动之上的所有活动并将目标活动置于栈顶。 - **FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET**:当任务栈被重置时,此活动也会被清除。 ...

    android+java面试

    - FLAG_ACTIVITY_CLEAR_TOP:回到栈顶Activity,清除中间所有Activity。 - FLAG_ACTIVITY_SINGLE_TOP:栈顶Activity已存在时不创建新实例。 9. **Activity生命周期** - onCreate():Activity首次创建。 - ...

    android用于打开各种文件的intent.docx

    - `addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)`:设置标志位,表示当任务被清除时,活动也会被清除。 #### 五、注意事项 1. **MIME类型**:正确设置MIME类型对于打开文件至关重要。不同的文件类型需要...

Global site tag (gtag.js) - Google Analytics