一、Activity与任务
一个activity可以启动另外一个,甚至包括与它不处于同一应用程序之中的。举个例子说,假设你想让用户看到某个地方的街道地图。而已经存在一个具有此功能的activity了,那么你的activity所需要做的工作就是把请求信息放到一个Intent对象里面,并把它传递给startActivity()。于是地图浏览器就会显示那个地图。而当用户按下BACK键的时候,你的activity又会再一次的显示在屏幕上。
对于用户来说,这看起来就像是地图浏览器是你activity所在的应用程序中的一个组成部分,其实它是在另外一个应用程序中定义,并运行在那个应用程序的进程之中的。Android将这两个activity放在同一个任务中来维持一个完整的用户体验。简单的说,任务就是用户所体验到的“应用程序”。它是安排在一个堆栈中的一组相关的activity。堆栈中的根activity就是启动了这整个任务的那个MainActivity(一般情况下,它就是应用程序的启动Activity)。而堆栈最上方的activity则是当前运行的──用户直接对其进行操作的。当一个activity启动另外一个的时候,新的activity就被压入堆栈,并成为当前运行的activity。而前一个activity仍保持在堆栈之中。当用户按下BACK键的时候,当前activity出栈,而前一个恢复为当前运行的activity。
堆栈中保存的其实是对象,所以如果发生了诸如需要多个地图浏览器的情况,就会使得一个任务中出现多个同一Activity子类的实例同时存在,堆栈会为每个实例单独开辟一个入口。堆栈中的Activity永远不会重排,只会压入或弹出。
任务其实就是activity的堆栈,你无法撇开activity而为一个任务设置一个值。事实上整个任务使用的值是在根activity中设置的。比如说,下一节我们会谈及“任务的affinity”,从affinity中读出的值将会设置到任务的根activity之中。
任务中的所有activity是作为一个整体进行移动的。整个的任务(即activity堆栈)可以移到前台,或退至后台。举个例子说,比如当前任务A在堆栈中存有四个activity,三个在当前activity之下。当用户按下HOME键的时候,回到了应用程序加载器,然后选择了一个新的应用程序B(也就是一个新任务)。则当前任务A遁入后台,而新任务B的根activity显示出来。然后,过了一小会儿,用户再次回到了应用程序加载器而又选择了前一个应用程序A(上一个任务)。于是那个任务A,带着它堆栈中所有的四个activity,再一次的到了前台。当用户按下BACK键的时候,屏幕不会显示出用户刚才离开的应用程序B的根activity。取而代之,当前任务A堆栈中最上面的activity被弹出,而同一任务中的上一个activity显示了出来。
上述即是activity和任务的默认行为模式。但是有一些方法可以改变所有这一切。关于activity和任务的联系,任务中activity的行为方式都被启动activity的Intent对象的标志和manifest文件中<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堆栈)
默认情况下,一个应用程序中的activity相互之间会有一种吸引力(Affinity),就是说,不进行特殊设置的话,它们首选都归属于一个任务。然而,可以在<activity>元素中把每个activity的task affinity属性设置为一个独立的affinity。于是在不同的应用程序中定义的activity可以享有同一个affinity,或者在同一个应用程序中定义的activity有着不同的affinity。affinity在两种情况下生效:当加载activity的Intent对象包含了FLAG_ACTIVITY_NEW_TASK 标记,或者当activity的allowTaskReparenting属性设置为“true”。
FLAG_ACTIVITY_NEW_TASK标记
如前所述,在默认情况下,一个新activity被另一个Activity调用了startActivity()方法,载入任务之中。并压入了调用者所在的堆栈。然而,如果传递给startActivity()的Intent对象包含了FLAG_ACTIVITY_NEW_TASK标记,系统会为新activity安排另外一个任务。一般情况下,如同标记所暗示的那样,这会是一个新任务。然而,这并不是必然的。如果已经存在了一个与新activity有着同样affinity的任务,则activity会载入那个任务之中。如果没有,则启用新任务。
allowTaskReparenting 属性
如果一个activity将allowTaskReparenting属性设置为“true”。它就可以从初始的任务中转移到与其拥有同一个affinity并转向前台的任务之中。比如说,一个旅行应用程序中包含的预报所选城市的天气情况的activity。它与这个应用程序中其它的activity拥有同样的affinity(默认的affinity)而且允许重定父级。你的另一个activity启动了天气预报,于是它就会与这个activity共处与同一任务之中。然而,当那个旅行应用程序再次回到前台的时候,这个天气预报activity就会被再次安排到原先的任务之中并显示出来。如果在用户的角度看来,一个.apk文件中包含了多于一个的“应用程序”,你可能会想要为它们所辖的activity安排不一样的affinity。
三、Activity加载模式
<activity>元素的launchMode属性可以设置四种不同的加载模式:
“standard”(默认值)
“singleTop”
“singleTask”
“singleInstance”
这些模式之间的差异主要体现在四个方面:
intent启动的activity归属于哪个任务。对“standard”和“singleTop”模式而言,是调用startActivity发出intent的那个任务,除非Intent对象包含FLAG_ACTIVITY_NEW_TASK标记。而在这种情况下,如同上面Affinitie和新任务一节所述,会是另外一个任务。相反,对“singleTask”和“singleInstance”模式而言,activity总是位于任务的根部。正是它们定义了一个任务,所以它们绝不会被载入到其它任务之中。
同一activity是否可以存在多个实例。一个“standard”或“singleTop”的activity可以被多次初始化。它们可以归属于多个任务,而一个任务也可以拥有同一activity的多个实例。相反,对“singleTask”和“singleInstance”的activity被限定于只能有一个实例。因为这些activity都是任务的起源,这种限制意味着在一个设备中同一时间只允许存在一个任务的实例。
在实例所在的任务中是否会有别的activity。设置“singleInstance”模式的activity将以唯一的姿态出现在它所在的任务中。如果它启动了别的activity,那个activity将会加载到其它的任务中去──就好像在intent中设置了FLAG_ACTIVITY_NEW_TASK 标记一样的效果。在其它方面,“singleInstance”模式的效果与“singleTask”是一样的。剩下的三种模式允许一个任务中出现多个activity。“singleTask”模式的activity将是任务的根activity,但它可以启动别的activity并将它们置入所在的任务中(注意这是它与singleInstance的主要区别)。“standard”和“singleTop”模式的activity可以在堆栈的任意位置出现。
是否要载入新的类实例以处理新的intent。对默认的“standard”模式来说,对于每个新intent都会创建一个新的实例以进行响应,每个实例仅处理一个intent。“singleTop”模式下,如果activity位于目的任务堆栈的最上面,则重用目前现存的activity来处理新的intent。如果它不是在堆栈顶部,则不会发生重用。而是创建一个新实例来处理新的intent并将其推入堆栈。举例来说,假设一个任务的堆栈由根activityA和activity B、C和位于堆栈顶部的D组成,即堆栈A-B-C-D。一个针对D类型的activity的intent抵达的时候,如果D是默认的“standard”加载模式,则创建并加载一个新的类实例,于是堆栈变为A-B-C-D-D。 然而,如果D的载入模式为“singleTop”,则现有的实例会对新intent进行处理(因为它位于堆栈顶部)而堆栈保持A-B-C-D的形态。换个角度来说,如果新抵达的intent是针对B类型的activity,则无论B的模式是“standard”还是“singleTop” ,都会加载一个新的B的实例(因为B不位于堆栈的顶部),而堆栈的顺序变为A-B-C-D-B。如前所述,“singleTask”或“singleInstance”模式的activity永远不会存在多于一个实例。所以实例将处理所有新的intent。一个“singleInstance”模式的activity永远保持在堆栈的顶部(因为它是那个堆栈中唯一的一个activity),所以它一直坚守在处理intent的岗位上。然而,对一个“singleTask”模式的activity来说,它上面可能有,也可能没有别的activity和它处于同一堆栈。在有的情况下,它就不在能够处在处理intent的位置上,所以该intent将被舍弃。(即便在intent被舍弃的情况下,它的抵达仍将使这个任务切换至前台,并一直保留)
当一个现存的activity被要求处理一个新的intent的时候(对于现存activity来说,new intent的理解应该是该activity启动以后,向该activity发送的intent为new intent),会调用onNewIntent()方法来将intent对象传递至activity。
请注意,当一个新的activity实例被创建以处理新的intent的时候,用户总可以按下BACK键来回到前面的状态(回到前一个activity)。但当使用现存的activity来处理新intent的时候,用户是不能靠按下BACK键回到当这个新intent抵达之前的状态的。
四、清理堆栈
如果用户离开一个任务很长一段时间,系统会清理该任务中除了根activity之外的所有activity。当用户再次回到这个任务的时候,除了只剩下初始化activity尚存之外,其余都跟用户上次离开它的时候一样。这样做的原因是:在一段时间之后,用户再次回到一个任务的时候,他们更期望放弃他们之前的所作所为,做些新的事情。
这些属于默认行为,另外,也存在一些activity的属性用以控制并改变这些行为:
alwaysRetainTaskState 属性
如果一个任务的根activity中此属性设置为“true”,则上述默认行为不会发生。任务将在很长的一段时间内保留它堆栈内的所有activity。
clearTaskOnLaunch属性
如果一个任务的根activity中此属性设置为“true”,则每当用户离开这个任务和返回它的时候,堆栈都会被清空至只留下rootactivity。换句话说,这是alwaysRetainTaskState的另一个极端。哪怕仅是过了一小会儿,用户回到任务时,也是见到它的初始状态。
finishOnTaskLaunch属性
这个属性与clearTaskOnLaunch属性相似,但它仅作用于单个的activity,而不是整个的task。而且它可以使任意activity都被清理,甚至根activity也不例外。当它设置为“true”的时候,此activity仅做为任务的一部分存在于当前回话中,一旦用户离开并再次回到这个任务,此activity将不复存在。
此外,还有别的方式从堆栈中移除一个activity。如果一个intent对象包含FLAG_ACTIVITY_CLEAR_TOP标记,而且目标任务的堆栈中已经存在了一个能够响应此intent的activity类型的实例。则这个实例之上的所有activity都将被清理以使它位于堆栈的顶部来对intent做出响应。如果此时指定的activity的加载模式为“standard”,则它本身也会从堆栈中移除,并加载一个新的实例来处理到来的intent。这是因为加载模式为“standard”的activity总会创建一个新实例来处理新的intent。
FLAG_ACTIVITY_CLEAR_TOP与FLAG_ACTIVITY_NEW_TASK经常合并使用。这时,这些标记提供了一种定位其它任务中现存的activity并将它们置于可以对intent做出响应的位置的方法。
五、启动任务
当一个activity被指定一个“android.intent.action.MAIN”做为动作,以及“android.intent.category.LAUNCHER”做为类别的intent过滤器之后(在前述intent过滤器一节中已经有了这个示例),它就被设置为一个任务的入口点。这样的过滤器设置会在应用程序加载器中为此activity显示一个图标和标签,以供用户加载任务或加载之后在任意时间回到这个任务。
第二个能力相当重要:用户必须可以离开一个任务,并在一段时间后返回它。出于这个考虑,加载模式被设定为“singleTask”和“singleInstance”的activity总是会初始化一个新任务,这样的activity仅能用于指定了一个MAIN和LAUNCHER过滤器的情况之下。我们来举例说明如果没指定过滤器的情况下会发生的事情:一个intent加载了一个“singleTask”的activity,初始化了一个新任务,用户在这个任务中花费了一些时间来完成工作。然后用户按下了HOME键。于是任务被要求转至后台并被主屏幕所掩盖。因为它并没有在应用程序加载器中显示图标,这将导致用户无法再返回它。
类似的困境也可由FLAG_ACTIVITY_NEW_TASK标记引起。如果此标记使一个activity启动了一个新任务继而用户按下了HOME键离开了它,则用户必须要有一些方法再次回到这个任务。一些实体(诸如通知管理器)总是在另外的任务中启动新activity,而不是做为它们自己的一部分,所以它们总是将FLAG_ACTIVITY_NEW_TASK标记包含在intent里面并传递给startActivity()。如果你写了一个能被外部实体使用这个标记调用的activity,你必须注意要给用户留一个返回这个被外部实体启动的任务的方法。当你不想让用户再次返回一个activity的情况下,可以将 <activity> 元素的 finishOnTaskLaunch设置为“true”。</activity></activity></activity></activity></activity>
分享到:
相关推荐
点击通知启动多个Activity.从启动Activity 返回不会退出app,而是返回到App 的MainActivity 或者其他Activity
activity生命周期、线程优先级、异常销毁、任务栈 参考代码
Android中的任务栈与Activity的启动模式.pdf 学习资料 复习资料 教学资源
如果在任务的栈顶正好存在该Activity的实例,就重用该实例,并且会调用实例的OnNewIntent()方法,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。 3.singleTask ...
Activity学习资料汇总,包括: Activity入门介绍 初始化,部署,启动,查看完成个人任务 部署流程资源的三种方式 流程的增删改查 流程变量的设置和获取 流程执行历史记录 连线 排他网关(连线条件变量) 并行网关 接收...
本节课程内容:Activity启动模式与跳转 Android中采用任务栈的形式来管Activity。栈是一种“先进后出”的数据结构。 Android中的任务栈 Task Stack in Android Activity的启动模式 Activity startup mode Activity...
异步任务中Activity销毁时的代码示例
如果在进行异步任务,如进行下载时,该示例保证在旋转屏幕,不会对加载任务进行中断重启,并且对话框正常显示。
【任务和结果】 1.掌握Activity的组成结构和创建过程。结合Hello World程序,叙述Android程序运行过程和执行结果。 2.了解常用的Activity的生命周期方法,并通过程序验证Activity的执行过程。 3.创建简单注册页面,...
结合谷歌官方的例子写的一个Fragment与Activity之间通过回调接口通信的例子。 结合谷歌官方的例子写的一个Fragment与Activity之间通过回调接口通信的例子。
10.0任务列表获取缩略图,获取最近任务,仿7.0UI,直接引入加载即可。
审批分为:员工用户、部门经理、boss三种角色
在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,...
原创博客:https://blog.csdn.net/a704020443/article/details/107939512 里面有介绍
提 示:设计5个任务:Task0 、 Task1 、Task2 、Task3 、Task4 ,其优先级关系Task0>Task1>Task2>Task3>Task4。定义 5 个信号量 Sem0、 Sem1、 Sem2、 Sem3、 Sem4,每个任务 i 均作相同的工作:申请信号量 i, (i+1)...
activiti没有撤回,由于业务的需求需要实现撤回,在参考别人代码后以两种方式实现了任意...5、领取任务,完成任务 6、删除当前节点的流向,将流向还原成临时变量oldPvmTransitionList中的值 第二种方式具体看代码。。。
Activiti多实例任务实现会签.
包含流程的部署、删除流程实例、激活挂起、获取部署对象、启动流程、设置批注、查询个人任务等相关API接口
本篇文章主要介绍了Android中Service与Activity之间通信的几种方式,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,具有一定的参考价值,有兴趣的可以了解一下。
1、 完成启动界面的设计,要求采用合理布局,使界面效果与图1所示结果保持一致。( “男”单选按钮默认选中,学院下拉列表框的内容为:信息技术学院、外国语学院、机电学院、商学院、艺术设计学院、珠宝学院、新闻...