zoukankan      html  css  js  c++  java
  • android 之 Task Activity(转载)

    首先task包含一个或多个activity,它是安排在一个堆栈中的一组相关的activity。堆栈中的根activity就是启动了这整个任务的那个MainActivity(一般情况下,它就是应用程序的启动Activity)。而堆栈最上方的activity则是当前运行的──用户直接对其进行操作的。当一个activity启动另外一个的时候,新的activity就被压入堆栈,并成为当前运行的activity。而前一个activity仍保持在堆栈之中。当用户按下BACK键的时候,当前activity出栈,而前一个恢复为当前运行的activity。

    --------------------------------------------------------------------

    这里一定要注意栈的特性:只有压入和弹出。

    堆栈中保存的其实是对象,如果一个应用中多次使用了一个activity,那么就会使同一个任务中出现多个该activity的对象。堆栈中很可能从下到上出现这种排序A-B-C-A-D-A.我们无法撇开activity而单独的给任务设置一些值。因为整个任务的属性其实就是再根activity(所谓根activity就是存储在任务栈最底层的那个activity)中进行设置的。

        任务中的所有activity是作为一个整体进行移动的。整个的任务(即activity堆栈)可以移到前台,或退至后台。举个例子说,比如当前任务A在堆栈中存有四个activity。当用户按下HOME键的时候,回到了home screen,然后选择了一个新的应用程序B(也就是一个新任务)。则当前任务A遁入后台,而新任务B的根activity显示出来。然后,过了一小会儿,用户再次回到了应用程序加载器而又选择了前一个应用程序A(上一个任务)。于是那个任务A,带着它堆栈中所有的四个activity,再一次的到了前台。当用户按下BACK键的时候,屏幕不会显示出用户刚才离开的应用程序B的根activity。取而代之,当前任务A堆栈中最上面的activity被弹出,而同一任务中的上一个activity显示了出来。

    上面所说的这些都是系统默认的行为。我们是可以通过一些办法来改变的。下面我们就详细的介绍一下:

    一般,我们可以在两个地方对任务的一些属性进行设置。一个地方是启动任务的Intent中,另一个地方就是AndroidManifest.xml中的<Activity>标签中。

    关键的Intent标记包括

    FLAG_ACTIVITY_NEW_TASK

    FLAG_ACTIVITY_CLEAR_TOP

    FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

    FLAG_ACTIVITY_SINGLE_TOP

    关键的<activity>属性是:

    taskAffinity

    launchMode

    allowTaskReparenting

    clearTaskOnLaunch

    alwaysRetainTaskState

    finishOnTaskLaunch

    affinity:

        一般来说,相同应用中的activity具有亲和度(也有人成为吸引力,英文为affinity),如果不进行显示的设置,他们默认会放在同一个任务当中。affinity可以通过android:taskAffinity属性进行设置。任务的affinity属性是从根activity中读取的。拥有相同的affinity的Activity理论上属于相同的Task(在用户的角度是相同的“应用程序”)。Task的affinity是由它的根Activity决定的。

    affinity决定两件事情——Activity重新宿主(从一个Task跳到了另一个Task中,新的Task就被称为重新宿主)的Task(参考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK标志启动的Activity宿主的Task。

    默认情况,一个应用程序中的所有Activity都拥有相同的affinity。你可以通过设定这个特性来重组它们,甚至可以把不同应用程序中定义的Activity放置到相同的Task中。如果不指定改activity到底属于哪个task,则可以将affinity设置为空字符串。 如果这个特性没有设置,Activity将从应用程序的设定那里继承下来(参考<application>元素的taskAffinity特性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。

    注意:affinity只有在加载activity的Intent对象包含了FLAG_ACTIVITY_NEW_TASK 标记,或者当activity的allowTaskReparenting属性设置为“true”时才有效。

    通过Intent设置的属性:

    FLAG_ACTIVITY_NEW_TASK

        如前所述,在默认情况下,一个新activity被另一个Activity调用了startActivity()方法,载入任务之中。并压入了调用者所在的堆栈。然而,如果传递给startActivity()的Intent对象包含了FLAG_ACTIVITY_NEW_TASK标记,系统会为新activity安排另外一个任务。一般情况下,如同标记所暗示的那样,这会是一个新任务。然而,这并不是必然的。如果已经存在了一个与新activity有着同样affinity的任务,则activity会载入那个任务之中。如果没有,则启用新任务。

        简言之:有相同affinity的任务,则压入该任务,否则创建一个新的任务。

     FLAG_ACTIVITY_CLEAR_TOP

        如果intent将要启动的activity已经存在于一个Task中,那么这个Task中该activity上面的那些activity都会被移除销毁,然后这个intent将会作为一个新的intent投递给目标activity(目标activity已经位于栈的顶端了);

    例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。

        上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为“multiple”(默认值),并且你没有在这个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_CLEAR_WHEN_TASK_RESET
        如果设置,这将在Task的Activity stack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。

    这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面选择e-mail app,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下次用户返回到mail程序时都将全部清除。

    FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
        如果设置,新的Activity不会在最近启动的Activity的列表中保存。

    FLAG_ACTIVITY_SINGLE_TOP
        如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的。

    其他的一些标识:(了解)

    FLAG_ACTIVITY_FORWARD_RESULT

        如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的Activity。

    FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

        这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。

    FLAG_ACTIVITY_MULTIPLE_TASK

        不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。

        由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。

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

    FLAG_ACTIVITY_NO_ANIMATION

        如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。

    FLAG_ACTIVITY_NO_HISTORY

        如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。

    <Activity>属性

    android:allowTaskReparenting
        用来标记Activity能否从启动的Task移动到有着相同affinity的Task(当这个Task进入到前台时)——“true”,表示能移动,“false”,表示它必须呆在启动时的那个Task里。如果这个特性没有被设定,设定到<application>元素上的allowTaskReparenting特性的值会应用到Activity上。默认值为“false”。
        一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来强制Activity移动到有着affinity的Task中。典型用法是:把一个应用程序的Activity移到另一个应用程序的主Task中。

    android:alwaysRetainTaskState

        用来标记Activity所在的Task的状态是否总是由系统来保持——“true”,表示总是;“false”,表示在某种情形下允许系统恢复Task到它的初始化状态。默认值是“false”。这个特性只针对Task的根Activity有意义;对其它Activity来说,忽略之。

        一般来说,特定的情形如当用户从主画面重新选择这个Task时,系统会对这个Task进行清理(从stack中删除位于根Activity之上的所有Activivity)。典型的情况,当用户有一段时间没有访问这个Task时也会这么做,例如30分钟。

    然而,当这个特性设为“true”时,用户总是能回到这个Task的最新状态,无论他们是如何启动的。这非常有用,例如,像Browser应用程序,这里有很多的状态(例如多个打开的Tab),用户不想丢失这些状态。系统会为我们保持这些状态数据。

    android:clearTaskOnLaunch

        用来标记是否从Task中清除所有的Activity,除了根Activity外(每当从主画面重新启动时)——“true”,表示总是清除至它的根Activity,“false”表示不。默认值是“false”。这个特性只对启动一个新的Task的Activity(根Activity)有意义;对Task中其它的Activity忽略。

        当这个值为“true”,每次用户重新启动这个Task时,都会进入到它的根Activity中,不管这个Task最后在做些什么,也不管用户是使用BACK还是HOME离开的。当这个值为“false”时,可能会在一些情形下(参考alwaysRetainTaskState特性)清除Task的Activity,但不总是。

        假设,某人从主画面启动了Activity P,并从那里迁移至Activity Q。接下来用户按下HOME,然后返回Activity P。一般,用户可能见到的是Activity Q,因为它是P的Task中最后工作的内容。然而,如果P设定这个特性为“true”,当用户按下HOME并使这个Task再次进入前台时,其上的所有的Activity(在这里是Q)都将被清除。因此,当返回到这个Task时,用户只能看到P。

        如果这个特性和allowTaskReparenting都设定为“true”,那些能重新宿主的Activity会移动到共享affinity的Task中;剩下的Activity都将被抛弃,如上所述。

    android:finishOnTaskLaunch
        用来标记当用户再次启动它的Task(在主画面选择这个Task)时已经存在的Activity实例是否要关闭(结束)——“true”,表示应该关闭,“false”表示不关闭。默认值是“false”。
        如果这个特性和allowTaskReparenting都设定为“true”,这个特性胜出。Activity的affinity忽略。这个Activity不会重新宿主,但是会销毁。

    android:launchMode

        用于指示Activity如何启动。这里有四种模式,与Intent对象中的Activity Flags(FLAG_ACTIVITY_*变量)共同作用,来决定Activity如何启动来处理Intent。它们是:

        "standard"

        "singleTop"

        "singleTask"

        "singleInstance"

        默认模式是“standard”。

       

        这些模式可以分成两大组别,“standard”和“singleTop”一组,“singleTask”和“singleInstance”一组。具有“standard”和“singleTop”启动模式的Activity可以实例化很多次。这些实例可以属于任何Task并且可以位于Activity stack的任何位置。典型的情况是,它们会进入调用startActivity()的Task(除非Intent对象包含FLAG_ACTIVITY_NEW_TASK标志,在这种情况下会选择一个不同的Task——参考taskAffinity特性)。

        相反的,“singleTask”和“singleInstance”只能启动一个Task。它们总是位于Activity stack的底部。甚至,设备一次只能拥有一个Activity的实例——只有一个这样的Task。

        “standard”和“singleTop”模式只在一种情况下有差别:每次有一个新的启动“standard”Activity的Intent,就会创建一个新的实例来响应这个Intent。每个实例处理一个Intent。相似的,一个“singleTop”的Activity实例也有可能被创建来处理新的Intent。然而,如果目标Task已经有一个存在的实例并且位于stack的顶部,那么,这个实例就会接收到这个新的Intent(调用onNewIntent());不会创建新的实例。在其他情况下——例如,如果存在的“singleTop”的Activity实例在目标Task中,但不是在stack的顶部,或者它在一个stack的顶部,但不是在目标Task中——新的实例都会被创建并压入stack中。

        “singleTask”和“singleInstance”模式也只在一种情况下有差别:“singleTask”Activity允许其它Activity成为它的Task的部分。它位于Activity stack的底部,其它Activity(必须是“standard”和“singleTop”Activity)可以启动加入到相同的Task中。“singleInstance”Activity,换句话说,不允许其它Activity成为它的Task的部分。它是Task中的唯一Activity。如果它启动其它的Activity,这个Activity会被放置到另一个task中——好像Intent中包含了FLAG_ACTIVITY_NEW_TASK标志。

    android:noHistory
        用于标记当用户从Activity上离开并且它在屏幕上不再可见时Activity是否从Activity stack中清除并结束(调用finish()方法)——“true”,表示它应该关闭,“false”,表示不需要。默认值是“false”。
        “true”值意味着Activity不会留下历史痕迹。因为它不会在Activity stack的Task中保留,因此,用户不能返回它

    启动Task

    如果一个Activity的Intent Filter的action为“android.intent.action.MAIN”、category为“android.intent.category.LAUNCHER”时,它就可以作为一个Task的入口点。有这种类型的Filter会在导致这个Activity在应用程序启动栏显示一个图标和标签,给用户提供一个方式可以启动这个Task和在任何时候可以再次回到这个Task。

    第二个能力很重要:用户一定可以离开一个Task,然后可以再次回到它。基于这个原因,两个启动模式,“singleTask”和“singleInstance”应该只在有MAIN和LAUNCHER的Activity上使用。例如,假设这个Filter没有的话:一个Intent启动了一个“singleTask”Activity,初始化一个新的Task,然后用户花费了一些时间在它上面。然后,用户按下HOME键。现在,这个Task处于后台并且被HOME画面遮盖。由于它不能在应用程序启动栏显示,用户就没有办法可以返回它。

    如果你不想用户回到某个Activity,可以把<activity>元素的finishOnTaskLaunch设置为“true”。

    原文: http://blog.csdn.net/chenzheng_java/article/details/6216621

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/sunnyfarmer/p/3016771.html
Copyright © 2011-2022 走看看