关于Activity启动模式的理解

        看了好几次Activity的启动模式,一直没有自己总结,总是看着就忘记了。于是这次打算自己写下来,加深对这部分知识的理解。至于为啥总是看着Activity启动模式,当然我又看的必要性,以后再说对我工作的需要的吧!

        本文没有什么创新性,主要参考了博客:Android中Activity四种启动模式和taskAffinity属性详解

        在<activity/>节点中,有个名为:android:launch=的属性,其默认值有4个,分别是standard,singleTop;singleTask和singleInstance。前两种为一组,理解比较简单,个人基本掌握,本文不在阐述。后两种启动模式较为复杂,常常还会引发一些安全问题,下面就这两种模式做一些记录和自己的理解。算是备忘也算是知识积累的过程 。

一、task是什么

       简单一句话,task是针对Activity管理提出的概念,task和Activity栈有关,task可以跨应用和快进程实现对Activity的管理。

二、对singleTask启动模式的理解

      整个过程基本参考前面说的那篇博文,本文没有向那位作者那样做详细的实验,实验可参考上面链接博文,有空再去修改自己这篇吧!

1、android:taskAffinity=属性

      (1)此属性的名字不做翻译解释,翻译显得生硬;

      (2)具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务;

      (3)一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity,即同一个任务的affinity是一样的;

       (4)这个属性决定两件事:当activity被re-parent时,它可以被re-paren哪个任务中;当activity以FLAG_ACTIVITY_NEW_TASK标志启动时,它会被启动到哪个任务中。(这个比较难以理解,请结合<activity>中的属性allowTaskReparenting和Intent中的标志  FLAG_ACTIVITY_NEW_TASK加以理解);

      (5)默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把不同的应用中的activity的taskAffinity设置成相同的值;

      (6)为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task。

2、只设定android:launchMode=single不设定android:taskAffinity=" "属性时

       根据上面第(5)条,taskAffinity可以影响当activity以FLAG_ACTIVITY_NEW_TASK标志启动时,它会被启动到哪个任务中。这句话的意思是,当新启动的activity(SecondActivity)是以FLAG_ACTIVITY_NEW_TASK标志启动时(可以认为FLAG_ACTIVITY_NEW_TASK和singleTask作用相同,当启动模式为singleTask时,framework会将它的启动标志设为FLAG_ACTIVITY_NEW_TASK),framework会检索是否已经存在了一个affinity为com.test.second的任务(即一个TaskRecord对象)

  • 如果存在这样的一个任务,则检查在这个任务中是否已经有了一个SecondActivity的实例
       a)如果已经存在一个SecondActivity的实例,则会重用这个任务和任务中的SecondActivity实例,将这个任务调到前台,清除位于SecondActivity上面的所有Activity,显示SecondActivity,并调用SecondActivity的onNewIntent()(这样 SecondActivity上面的Activity就被销毁了)

                 

       b)如果不存在一个SecondActivity的实例,会在这个任务中创建SecondActivity的实例,并调用onCreate()方法;

                                  

  • 如果不存在这样的一个任务,会创建一个新的affinity为com.test.second的任务,并且将SecondActivity启动到这个新的任务中;

3、同时设定android:launchMode=single和android:taskAffinity="com.test.second"属性时

  • 在MainActivity启动SecondActivity时,发现启动模式为singleTask,那么设定他的启动标志为FLAG_ACTIVITY_NEW_TASK;
  • 然后获得SecondActivity的taskAffinity,即com.test.second;
  • 检查是否已经存在一个affinity为com.test.second的任务,这个任务是不存在的;
  • 创建一个新的affinity为com.test.second的任务,并且将SecondActivity启动到这个新的任务中
     这一模式下,和上面不设置android:taskAffinity=属性时第二种情况类似。

     framework中对任务和activity‘的调度是很复杂的,尤其是把启动模式设为singleTask或者以FLAG_ACTIVITY_NEW_TASK标志启动时。所以,在使用singleTask和FLAG_ACTIVITY_NEW_TASK时,要仔细测试应用程序。这也是官方文档上的建议。

4、两个不同app中的不同的singleTask模式的Activity的taskAffinity设成相同

     过程懒得写了,看上面那篇博客吧,复制了结论:任务(Task)不仅可以跨应用(Application),还可以跨进程(Process)。

5、在同一个任务中具有唯一性

见博客:Android中Activity四种启动模式和taskAffinity属性详解

三、singleInstance启动模式

1、singleInstance启动特点

  • 以singleInstance模式启动的Activity具有全局唯一性,即整个系统中只会存在一个这样的实例
  • 以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中(官方文档上的描述为,singleInstance模式的Activity不允许其他Activity和它共存在一个任务中)
  • 被singleInstance模式的Activity开启的其他activity,能够开启一个新任务,但不一定开启新的任务,也可能在已有的一个任务中开启
             

2、启动过程说明

        从上面的图可以得出结论:被singleInstance模式的Activity A在开启另一activity B时,能够开启一个新任务,但是是不是真的开启新任务,还要受其他条件的限制,这个条件是:当前系统中是不是已经有了一个activity B的taskAffinity属性指定的任务。

        其实这种行为和singleTask启动时的情况相同。在Activity的启动模式设置为singleTask时,启动时系统会为它加上FLAG_ACTIVITY_NEW_TASK标志,而被singleInstance模式的Activity开启的activity,启动时系统也会为它加上FLAG_ACTIVITY_NEW_TASK标志,所以他们启动时的情况是相同的,上面说明singleTask时已经阐述过,现在重新说明一下:

        由于ThirdActivity是被启动模式为singleInstance类型的Activity(即SecondActivity)启动的,framework会为它它加上FLAG_ACTIVITY_NEW_TASK标志,这时 framework会检索是否已经存在了一个affinity为com.test.second(即ThirdActivity的taskAffinity属性)的任务,
  • 如果存在这样的一个任务,则检查在这个任务中是否已经有了一个ThirdActivity的实例,
         a)如果已经存在一个ThirdActivity的实例,则会重用这个任务和任务中的ThirdActivity实例,将这个任务调到前台,清除位于ThirdActivity上面的所有Activity,显示ThirdActivity,并调用ThirdActivity的onNewIntent()。
         b)如果不存在一个ThirdActivity的实例,会在这个任务中创建ThirdActivity的实例,并调用onCreate()方法
  • 如果不存在这样的一个任务,会创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将ThirdActivity启动到这个新的任务中
      如果ThirdActivity不设置taskAffinity,即ThirdActivity和MainActivity的taskAffinity相同,都为应用的包名,那么ThirdActivity是不会开启一个新任务的,framework中的判定过程如下:
         1)在SecondActivity启动ThirdActivity时,因为SecondActivity是singleInstance的,所以设定ThirdActivity的启动标志为 FLAG_ACTIVITY_NEW_TASK;
         2)然后获得ThirdActivity的taskAffinity,即为包名com.test;
         3)检查是否已经存在一个affinity为com.test的任务,这个任务是存在的,就是MainActivity所在的任务,这个任务是在启动 MainActivity时开启的;
         4)既然已经存在这个任务,就检索在这个任务中是否存在一个ThirdActivity的实例,发现不存在;
         5)在这个已有的任务中启动一个SecondActivity的实例。
为了作一个清楚的比较,列出ThirdActivity的taskAffinity属性设为com.jg.zhang.androidtasktest.second时的启动过程:
         1)在SecondActivity启动ThirdActivity时,因为SecondActivity是singleInstance的,那么设定ThirdActivity的启动标志为                                                         FLAG_ACTIVITY_NEW_TASK;
         2)然后获得ThirdActivity的taskAffinity,即为com.test.second;
         3)检查是否已经存在一个affinity为com.jg.zhang.androidtasktest.second的任务,这个任务是不存在的;
         4)创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将ThirdActivity启动到这个新的任务。

四、总结

        由上述可知,Task是Android Framework中的一个概念,Task是由一系列相关的Activity组成的,是一组相关Activity的集合。Task是以栈的形式来管理的。

      我们在操作软件的过程中,一定会涉及界面的跳转。其实在对界面进行跳转时,Android Framework既能在同一个任务中对Activity进行调度,也能以Task为单位进行整体调度。在启动模式为standard或singleTop时,一般是在同一个任务中对Activity进行调度,而在启动模式为singleTask或singleInstance是,一般会对Task进行整体调度。

对Task进行整体调度包括以下操作:
  • 按Home键,将之前的任务切换到后台
  • 长按Home键,会显示出最近执行过的任务列表
  • 在Launcher或HomeScreen点击app图标,开启一个新任务,或者是将已有的任务调度到前台
  • 启动singleTask模式的Activity时,会在系统中搜寻是否已经存在一个合适的任务,若存在,则会将这个任务调度到前台以重用这个任务。如果这个任务中已经存在一个要启动的Activity的实例,则清除这个实例之上的所有Activity,将这个实例显示给用户。如果这个已存在的任务中不存在一个要启动的Activity的实例,则在这个任务的顶端启动一个实例。若这个任务不存在,则会启动一个新的任务,在这个新的任务中启动这个singleTask模式的Activity的一个实例。
  • 启动singleInstance的Activity时,会在系统中搜寻是否已经存在一个这个Activity的实例,如果存在,会将这个实例所在的任务调度到前台,重用这个Activity的实例(该任务中只有这一个Activity),如果不存在,会开启一个新任务,并在这个新任务中启动这个singleInstance模式的Activity的一个实例。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值