Android Tasks、ActivityStack和Activity

来源:互联网 发布:网络音乐吧 点歌 编辑:程序博客网 时间:2024/06/05 04:28

最近又在开展一些Android的开发工作,出现了在个别场景下发生的Activity切换不符合预期的情况,于是来温习一下Android的Tasks、ActivityStack、Activity,以及影响到他们的几个重要参数launchMode、taskAffinity、IntentFlags


应用程序的进程与线程

从应用程序的角度来看,应用程序一般定义了应用对应的进程,以及上面运行着的一系列的线程。开发人员进行debug的时候的关注点会是哪个进程的哪个线程的哪个stacktrace。


Android四大组件

从Android应用程序的角度来看,除了进程和线程的这一个角度,从程序里面详细类的组织来看,Android应用程序包含有Activity、Service、ContentProvider、Broadcast Receiver4大组件,这四大组件就是通过我们之前说过的XML插件方式配置到AndroidManifest当中的。而这其中,Activity组件是Android应用程序界面开发最重要的一个部分。


Android系统界面用户体验组织(TASKS)

从Android系统界面的组织来看,用户体验到的直观界面都是由很多Tasks组成的。比如,我们从最近任务栏,就可以看到很多TASKS。用户可以随意的切换到其中的一个TASK。也可以按HOME键退出一个TASK。TASK的组织形式是ActivityStack,一个ActivityStack是由好多Activity组成的堆栈。从Android系统设计者的角度来看,一个Task定义了一组行为,而这组行为是由跨多个应用程序的多个Activity组织而构成的。这个打破了以往由应用程序(进程)来定义的资源边界。一个Task就是一个场景的实现。从此构建系统用户体验和行为的边界在于TASK,而非应用程序或者进程。


Task

  • Task 是activities的集合,通过activity stack来管理,依靠先进后出队列来实现;
  • 每个task中都至少有一个activity,新实例出来的activity置于栈顶
  • Task可以被切换到后台

  • Activity Stack
      如上所诉,Activity承担了大量的显示和交互工作,从某种角度上将,我们看见的应用程序就是许多个Activity的组合。为了让这许多 Activity协同工作而不至于产生混乱,Android平台设计了一种堆栈机制用于管理Activity,其遵循先进后出的原则,系统总是显示位于栈 顶的Activity,从逻辑上将,位于栈顶的Activity也就是最后打开的Activity,这也是符合逻辑的。

      在操作应用程序时,每次启动新的Activity,都会将此压入Activity Stack,当用户执行返回操作时,移除Activity Stack顶上的Activity,这样就实现了返回上一个Activty的功能。直到用户一直返回到Home Screen,这时候可以理解为移除了Activity Stack所有的Activity,这个Activity Stack不再存在,应用程序也结束了运行。
  •       可以通过 adb shell dumpsys |grep ActivityRecord 来查看 TASKS的ActivityStacks
  • task的taskAffinity

  • taskAffinity 这个属性主要是决定持有每个activity属于哪个task。
  • 默认情况下,同一个包中的activity共享同一个affinity(任务共用性)。

  • task的launchMode
  • standard(default):standard,标准的Activity是可以随意插入到TASK中去的一个组织结构,可以去TaskA,也可以去TaskB,也可以去TaskC,直接并无任何的联系
  • singleTop,如果在任务的栈顶正好存在该Activity的实例,就重用该实例,否则就创建新的实例并放入栈顶。
  • singleTask,如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
  • singleInstance

  • Intent Flag介绍

    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。如果它的启动模式声明为“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_NEW_TASK     

       如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相同的次序。      这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。      使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。      这个标志不能用于调用方对已经启动的Activity请求结果。


    FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS    

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

     

    FLAG_ACTIVITY_FORWARD_RESULT     

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



  • 参考:

  • 1、来自Android launchMode的温馨提示

  • 2、Android启动模式图文详解


  • 0 0