专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
郭霖  ·  Android外接设备开发使用一网打尽 ·  昨天  
鸿洋  ·  Android ... ·  昨天  
鸿洋  ·  Android系统native进程之我是in ... ·  3 天前  
郭霖  ·  StateFlow 和 ... ·  1 周前  
郭霖  ·  Android 跨进程+解耦的数据持久化方案 ·  1 周前  
51好读  ›  专栏  ›  安卓开发精选

Activity 的 Task 以及 launchMode 研究

安卓开发精选  · 公众号  · android  · 2016-09-03 08:14

正文

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - dreamist

链接:http://android.jobbole.com/84446/

点击 → 了解如何加入专栏作者


android 的 Task 和 Back Stack


Task 简介


android 中的Task是一系列Activity的集合,用户通过操作多个Activity来完成一个Task。一个Task的具体实现就是一个包含多个Activity的栈,当用户进入某一个app的时候,app的入口Activity被压入栈底,用户每进入一个Activity,该Activity都会被添加到该app的栈顶。Task中的每个Activity的顺序是不会重新排列的,Task的动作只有进栈和出栈。在android中点击OverView Screen的按钮可以进到OverView Screen的界面,如图:



图中展示出了现在系统中所有的Task,最前面的是前台的Task,其他的是后台的Task。


更多的关于Task的信息请参考:官方文档


Back Stack 回退栈简介


回退栈指的是当用户点击返回键的时候,android系统会一个接一个地pop出Task中所保留的Activity。回退栈更多地是表示逻辑上的一个概念,可以理解成Task的逻辑抽象。


Task 和 Back Stack的关系


Task 可以理解成 Back Stack的一种具体实现。除了包括Activity的Task之外,android系统中的Fragment也是具有回退栈的,但是Fragment并没有像Activity的Task那样的东西。


Task 与 Activity


Activity 的实例化是依赖于Task的,它必须被加载到某一个Task中才可以,从另一个角度来看,Task就是Activity的容器。android 系统在启动一个Activity的时候,会在系统中寻找是否存在符合该Activity 的自身属性 和 启动该Activity的Intent的要求的Task(具体怎么寻找,会在下面讨论),有的话直接在在该Task中实例化一个Activity,没有的话则需要新建一个Task,再在其中对Activity进行实例化。


系统如何给一个Activity寻找它的归属Task?


Task 有一个关键的属性affinity(中文为亲缘、近缘等,但是感觉译成中文并不合适,遂用英文直接阐述了)。android中每一个Activity也都有一个叫做affinity的属性,Activity的affinity值可以在mainfest配置文件中通过标签的andrid:taskAffinity属性指定,如果没有指定的话则默认使用该Activity所在app的包名。每一个Task的affinity属性值等于该Task的root Activity 的affinity值。具有相同affnity的Activity在被系统实例化的时候更加容易被驾到同一个Task中。当然,这只是比较关键点额一个点,android系统在给Activity找Task的时候会受到非常多因素的影响,有来自Intent实例的众多flag,还有来自mainfest配置文件中Activity的众多配置信息,这是一个复杂的过程,本文不进行深入讨论。


launchMode 研究


launchMode简介


launchMode 是Activity类的一个属性,该属性包括4个具体值:standard、singleTop、singleTask、singleInstance。我们都知道,android系统中启动Activity是通过Intent实例进行的,当系统收到一个Intent的实例需要去启动指定的Activity的时候,android系统会根据目标Activity的该属性值来决定是要要创建新的该Activity实例以及如何在Task中创建该Activity的实例。这就是launchMode这个属性的作用。


launchMode 分为两个类别


  • 普通类型:用户常用的启动模式类型,大部分Activity都是这两种启动模式。包括standdard 和 singleTop 两种启动模式

  • 特殊类型:具有特殊的行为的启动模式,只针对特殊需求的使用。包括 singleTask 和 singleInstance 两种启动模式


官方文档对4中启动模式描述如下:


使用场景启动模式是否可以有多个实例?简介
普通类型standard系统默认的启动模式,当系统接收到一个Intent实例去启动一个standard模式的Activity时,系统总是会在目标栈的顶部创建一个新的activity实例,并把Intent的实例传进去。
普通类型singleTop视具体情况当系统接收到一个Intent实例去启动一个singleTop模式的Activity时,如果在目标栈的顶部存在一个该Activity的实例的话,那么系统就会重用这个Activity的实例而不创建新的实例,并回调该Activity的onNewIntent(Intent intent)方法把新的Intent实例当作方法参数传递进去;如果在目标栈的顶部没有该Activity的实例的话系统将会在新建一个Activity实例,与standard的行为就一样了。
特殊类型singleTask当系统接收到一个Intent实例去启动一个singleTask模式的Activity时,如果不存在该Activity的实例的话,系统会先创建一个新的Task,并在该Task底部里面创建一个该Activity的实例,随后把Intent实例传递进去;如果已经存在一个该Activity的实例的话,系统就不会再创建新的实例,那么系统就会重用这个Activity的实例而不创建新的实例,并回调该Activity的onNewIntent(Intent intent)方法把新的Intent实例当作方法参数传递进去,同时,该Activity实例所在的Task将会被调到前台
特殊类型singleInstance类似于singleTask,唯一不同的地方在于,singleInstance的Activity不允许自己的Task中存在其他的Activity实例,也就是说singleInstance的Activity永远是Task中唯一的一个Activity实例


launchMode 的定义


  • 静态定义:在目标Activity的mainfest中使用标签静态定义

  • 动态定义:在启动目标Activity的Intent对象中使用不同的flag定义,可以用来定义launchMode的flag有以下三个:


flag对应的launchMode
FLAG_ACTIVITY_NEW_TASKsingleTask
FLAG_ACTIVITY_SINGLE_TOPsingleTop
FLAG_ACTIVITY_CLEAR_TOP无对应的launchMode


note:在Activity A启动 Activity B的时候,假如B已经在mainfest文件中定义过launchMode,此时的Intent对象中也有定义launchMode,这时候以Activity A start B的时候以Intent中定义的为准。


典型使用场景


launchMode使用场景
standard绝大多数标准的跳转
singleTop新闻阅读类的内容页面,假如在一个新闻页面又打开了另一个新闻页面,这时候Task的顶端已经有该Activity的实例了,就不用再初始化了
singleTask通知栏启动其他app,一般都会在Intent中加上FLAG_ACTIVITY_NEW_TASK,相当于使用了singleTask

一些会影响 Task 行为的 mainfest中activity的属性


属性名称可取值意义
android:taskAffinity一个存在的包名表示该Activity与该包名具有亲缘,在该Activity启动的时候,会优先选择被添加进已经存在的具有亲缘关系的Task中。
android:allowTaskReparentingtrue, false如果一个Activity的该属性值是true,它先被一个外部app启动了,此时它存在于那个调用它的app的Task中,当与它有亲缘关系的Task被后台带回到前台的时候,系统会把它换到该Task中;如果值为false的话,就不会发生移动。
android:alwaysRetainTaskStatetrue,false正常情况下,当一个Task在后台待了很久之后,系统会把该Task的非root Activity都清除,只保留root Activity。但是假如root Activity的该属性值被设置为true的话,系统会保留该Task中所有的Activity。


android中Activity的launchMode总结


  • launchMode的作用,是让开发者可以在一定程度上决定自己的Activity该如何被系统实例化,从而来满足开发者的开发需求

  • launchMode一共分为两类,一类是普通开发者最常用的:standard 和 singleTop,其中standard是官方定义的最常见的也是默认的系统对Activity进行实例化的行为模式,singleTop在standard的基础上进行了点小的改动,当目标栈的顶部有Activity的实例的时候将不再对该Activity进行初始化而是直接使用现成的Activity实例,因为有很多的使用场景是standard不太合适而singleTop比较合适的;另一个类别的是普通开发者不常使用的,singleTask 和 singleInstance,官方并不推荐在通常的场景中使用该类的launchMode,只有在极少数特殊的情形中才去使用,该类launchMode的特点是Activity在系统中只会有一个实例存在,不同的地方在于singleInstance的Activity会独占一个Task,而singleTask的则不会。

  • launchMode可以在mainfest文件中静态地设置,同时,在代码中,通过Intent的几个flag也可以达到设置launchMode的目的。假如某一次启动一个Activity的时候,在Intent中指定了一个launchMode,而且该Activity本身已经在mainfest文件中设置了launchMode,那么这个时候系统会以Intent中指定的为准。android系统这样设计的目的,我想是为了让整个系统的Activity可以更方便地让其它Activity(可以不再一个app内)进行调用,这与android的开放的态度是一致的。


参考资料:


  • https://developer.android.com/guide/components/tasks-and-back-stack.html

  • https://developer.android.com/guide/topics/manifest/activity-element.html#aff

  • http://droidyue.com/blog/2015/08/16/dive-into-android-activity-launchmode/index.html

  • http://www.it610.com/article/5751414.htm


专栏作者简介( 点击 → 加入专栏作者 


dreamist:个人主页:jiakaiyang.comgithub页面: https://github.com/kaiyangjia

打赏支持作者写出更多好文章,谢谢!




------------------ 推荐 ------------------


范品社推出了十几款程序员、电影、美剧和物理题材的极客T恤单件 ¥59.9、两件减¥12、四件减¥28,详见网店商品页介绍。

网店地址:https://fanpinshe.taobao.com/

淘口令:复制以下红色内容,然后打开手淘即可购买

范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)