activity之栈管理

在android中,一个activity组件可以激活另一个activity组件:本程序activity和其它程序的activity。

若新的被激活的activity组件属于另一个应用程序,则那个activity组件会运行在那个应用程序的进程中,但是从用户的角度来看,好像就是属于本应用程序一样。Android是通过将之前的activity组件和新被激活的activity组件放入同一个任务栈来实现这个功能的。从用户的角度看,一个任务栈就代表了“一个应用程序”。它实际上是一个栈,里面放着一组被排列好的相关的activity组件。位于栈底的activity(根activity)就是开启这个任务栈的activity组件,一般情况下,就是应用程序的主界面。而位于栈顶的activity组件即代表当前被激活的activity组件(可接收用户行为的activity)。

任务栈中包含了activity组件的对象,且任务栈中可以包含有某一个activity组件类型的多个实例对象。在任务栈中的activity组件不能被重排序,只能被压栈和弹栈。

任务栈不是某个类型,也不是某一个元素,它是一组activity组件的组织形式。所以没有办法在不影响任务栈中的activity组件的情况下,单独设置任务栈的参数。根activity的参数既是整个任务栈的参数,它会影响任务栈中的所有activity组件。

当某个应用程序在前后台切换的时候,实际上就是代表这个应用程序的一个任务栈在前后台切换。

刚刚描述的行为是activity和任务栈的默认行为,但也有办法在很多方面对它进行修改:

1.taskAffinity和allowTaskReparenting使用

方法1:在发送的请求(即Intent对象)中设置一些标记。

方法2:在manifest文件中,对接收请求(即Intent对象)的activity组件设置一些属性。

所以在请求者和接收者中都可以进行控制。

在Intent对象中主要的标志有:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_SINGLE_TOP

在<activity>标签中,主要的属性有:

taskAffinity   android:taskAffinity="com.cardroid.sdhc"  表示两个应用里面的亲属关系,如果一个应用的某个Application1中的ActivityL1和另一个应用的Application2中的ActivityR1设置这个属性,其中ActivityL1的allowTaskReparenting=true允许任务栈动态加载。

然后,ActivityL1显示后点击HOME键盘,从另一个应用ActivityR1启动后就会显示点击HOME的那个ActivityL1在前台,因为ActivityL1为动态任务栈加载,同时由于taskAffinity的存在,所以加入到了ActivityR1任务栈中,并显示在前台。

接下来的内容就会讲解一些Intent标志和<activity>标签属性的作用和用法。

allowTaskReparenting

launchMode

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch

2.亲属关系和新的任务

默认情况下,一个应用程序中的activity组件彼此之间是亲属关系――也就是说它们属于同一个任务栈。但是我们可以通过设置某个<activity>标签的taskAffinity属性来为这个activity组件设置亲属关系。在不同的应用程序中定义的activity组件可以共用同一个亲属关系,或者在同一个的应用程序中定义的activity组件可以使用不同的亲属关系。每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。

如果一个Activity没有显式的指明该 Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根
Activity的taskAffinity的值。

一开始,创建的Activity都会在创建它的Task中,并且大部分都在这里度过了它的整个生命。然而有一些情况,创建的Activity会被分配其它的Task中去,有的甚至,本来在一个Task中,之后出现了转移。亲属关系会在两种情况下发挥作用:

1)负责激活activity组件的Intent对象中包含了FLAG_ACTIVITY_NEW_TASK标志。

2)被激活的activity组件的allowTaskReparenting属性被设置为“true”。

问题:

1.在同一个程序中,不同的Activity设置了相同的(默认)或不同的taskAffinity属性,那么在默认标志和FLAG_ACTIVITY_NEW_TASK时,会如何跳转?共有4中组合。

2.在跨程序启动Activity时,不同的Activity设置了相同的或不同的(默认)taskAffinity属性,那么在默认标志和FLAG_ACTIVITY_NEW_TASK时,会如何跳转?共有4中组合。

关于FLAG_ACTIVITY_NEW_TASK标志量

默认情况下,一个被激活的新activity会和负责激活它的那个activity组件存在于同一个任务栈中。但是若负责激活的Intent对象包含了FLAG_ACTIVITY_NEW_TASK标志,则系统会为存放那个即被激活的新activity寻找一个新的任务栈。此时,若已经存在了相同亲属关系的任务栈,则系统会直接将这个即被激活的新activity放入到这个任务栈中;否则系统会开始一个新的任务栈。

关于allowTaskReparenting属性

若一个activity组件的allowTaskReparenting被置为“true”,则当与这个activity有相同的亲属关系的任务栈被切换到前台的时候,这个activity会从当前存在的任务栈中移动到与其有相同的亲属关系的任务栈中。

若从用户的角度来看,一个.apk文件包含了一个以上的“应用程序”,那你可能要为那些activity组件指定不同的亲属关系。

3.启动模式

<activity>标签的launchMode属性可以设置为四种不同的模式:

“standard”(默认模式)

“singleTop”

android:launchMode="singleTop" 相当于每次都从这个ACITIVITY启动

“singleTask”

android:launchMode="singleTop" 和singleTop类似,不同于,每次启动后都在最上面

“singleInstance”

这几种模式的区别体现以下四点上:

1)当这个activity被激活的时候,会放入哪个任务栈。

对于“standard”和“singleTop”模式,这个新被激活的activity会放入和之前的activity相同的任务栈中――除非如前所述,Intent对象包含FLAG_ACTIVITY_NEW_TASK标志。

但“singleTask”和“singleInstance”模式则表示这个新被激活的activity不会放入已经存在的任务栈中,它会重新开启一个任务栈,并作为这个新的任务栈的根activity。

2)是否可以存在这个activity类型的多个实例。

对于“standard”和“singleTop”模式,可以有多个实例,并且这些实例可以属于不同的任务栈,每个任务栈Task也可以包含有这个activity类型的多个实例。

但“singleTask”和“singleInstance”模式则表示至多只可以存在这个activity类型的一个实例。并且这一点必须是根activity的限制,一个任务中只能被实例化一次。所以这意味着在同一时间,在手机上绝不会存在多于一个的由这个activity启动的任务栈。

3)包含此activity的任务栈是否可以包含其它的activity。

“singleInstance”模式表示包含此activity的任务栈不可以包含其它的activity。若此activity启动了另一个activity组件,那么无论那个activity组件的启动模式是什么或是Intent对象中是否包含了FLAG_ACTIVITY_NEW_TASK标志,它都会被放入另外的任务栈。在其它方面“singleInstance”模式和“singleTask”模式是一样的。

其余三种启动模式则允许包含此activity的任务栈包含其它的activity。

4)Whether a new instance of the class will be launched to handle a new intent.

对于默认的“standard”模式,每当响应一个Intent对象,都会创建一个这种activity类型的新的实例。即每一个activity实例处理一个intent。

对于“singleTop”模式,只有当这个activity的实例当前处于任务栈的栈顶位置,则它会被重复利用来处理新到达的intent对象。否则就和“standard”模式的行为一样。

正如第二点所说的,“singleTask”和“singleInstance”模式表示只能有一个实例,所以这个唯一的实例需要处理所有新到达的intent对象。又由于“singleInstance”模式的activity实例总是位于任务栈的栈顶,所以这样做很正常。

但对于“singleTask”模式的acitvity,如果发给该Activity的Intent对象到来时该Activity不在堆栈顶端,那么该Intent对象将被丢弃,但是界面还是会切换到当前的Activity。(虽然会被丢弃,但是这个intent对象会使这个任务栈切换到前台)

如果一个新到达的intent对象是被一个已经存在的activity组件来处理的,那么这个activity的onNewIntent(android.content.Intent)方法会被系统调用。

注意:若为了处理一个新到达的intent对象而创建了一个activity实例,则用户按下“BACK”键就会退到之前的那个activity。但若这个新到达的intent对象是由一个已经存在的activity组件来处理的,那么用户按下“BACK” 键就不会回退到处理这个新intent对象之前的状态了。

4.清理任务栈

如果一个任务栈在很长的一段时间都被用户保持在后台的,那么系统就会将这个任务栈中除了根activity以外的其它所有activity全部清除掉。从这之后,当用户再将任务栈切换到前台,则只能显示根activity了。

以上说的是默认模式,可以通过<activity>标签的一些属性来更改:

1)alwaysRetainTaskState属性

如果将根activity的alwaysRetainTaskState属性设置为“true”,则即便一个任务栈在很长的一段时间都被用户保持在后台的,系统也不会对这个任务栈进行清理。

2)clearTaskOnLaunch属性

如果将根activity的clearTaskOnLaunch属性设置为“true”,那么只有这个任务栈切换到了后台,那么系统就会将这个任务栈中除了根activity以外的其它所有activity全部清除掉。即和alwaysRetainTaskState的行为完全相反。

3) finishOnTaskLaunch属性

这个属性的行为类似于clearTaskOnLaunch,但是此属性作用于单个的activity对象,而不是整个任务栈。当这个任务栈切换到了后台,这个属性可以使任务栈清理包括根activity在内的任何activity对象。

这里也有另一种方法来使activity对象从任务栈中被移除。若Intent对象包含FLAG_ACTIVITY_CLEAR_TOP标志,并且在目标任务栈中已经存在了用于处理这个Intent对象的activity类型的一个实例,那么在任务栈中这个实例之上的所有activity实例会被移除。从而用于处理这个Intent对象的activity类型的那个实例会位于任务栈的栈顶,并用来处理那个Intent对象。若那个匹合的activity类型的启动模式是“standard”,则这个已经存在于任务栈中的匹合的activity类型的实例也会被移除,并且一个新的此类型activity的实例被创建并压栈来处理这个Intent对象。

FLAG_ACTIVITY_CLEAR_TOP这个标志经常和FLAG_ACTIVITY_NEW_TASK标志结合使用,这样结合使用的意思是在另一个任务栈中定位已经存在的匹合的activity类型的实例,并且让此实例位于栈顶。

5.启动任务栈

通过将一个activity类型的intent-filter的动作设置为“android.intent.action.MAIN”,类别设置为“android.intent.category.LAUNCHER”可以使这个activity实例称为一个任务栈的入口。拥有这种类型的intent-filter的activity类型的图表和名字也会显示在application
launcher中。

第二个能力是很重要的:用户必须能够使一个任务栈切换到后台,也可以随时将其切换到前台。出于这个原因,使activity在启动时新开任务栈的启动模式(即“singleTask”和“singleInstance”模式)只应该被利用在拥有拥有“android.intent.action.MAIN”动作和“android.intent.category.LAUNCHER”类别的intent-filter的activity类型上。

类似的限制同样体现在FLAG_ACTIVITY_NEW_TASK标志上。如果这个标志使一个activity开始了一个新的任务栈,并且用户点击“HOME”键将其切换到了后台,则必须有某种方式使用户可以重新将那个任务栈切换到前台。一些实例(比如通知管理器),总是在外部的任务栈中开启一个activity,而不是其自身的任务栈,所以它们总是将FLAG_ACTIVITY_NEW_TASK标志放入Intent对象中,并将Intent对象传入startActivity()方法中。

对于在某些情况下,你不希望用户能够返回到某一个activity,那么可以通过设置<activity>标签的“finishOnTaskLaunch”属性为“true”来实现。

参考:

taskAffinity

singalTask和singalInstace

activiy的任务栈

时间: 2024-08-18 01:09:50

activity之栈管理的相关文章

Android群英传笔记——第八章:Activity与Activity调用栈分析

Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命周期和管理方式,是了解Android的基础,本节主讲 Activity的生命周期与工作模式 Activity调用栈管理 一.Activity Activity作为四大组建出现平率最高的组件,我们在哪里都能看到他,就让我们一起先来了解一下他的生命周期 1.起源 Activity是用户交互的第一接口,他

activity栈管理的3种方式

一.背景 在android开发过程最经常使用的组件非activity莫属. 通过分析activity的各种跳转,执行同学能够分析用户的各种行为.更重要的一点是在做插件化的过程中,我们经常会对activity进行各种反射,来实现各种需求. 二.实现 2.1 通过对"android.app.ActivityThread"进行反射.获取android系统的activity栈 遍历activity栈能够得到当前应用中的全部存活的activity. Log.e("Baseactivty

第四章 Activity和Activity调用栈分析 系统信息与安全机制 性能优化

1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重新回到前台状态的时候会先调用onRestart方法,然后再调用后续的onStart等方法:(2)启动另一个Activity然后finish,先调用旧Activity的onPause方法,然后调用新的Activity的onCreate->onStart->onResume方法,然后调用旧Activity的onStop->onDestory方法.如

[Android]Fragment源码分析(肆) Fragment栈管理

Fragment的栈是Fragment管理颇为出彩的一部分,它跟Activity栈的本质差异除了在数据结构上和逻辑上的不同之外,主要区别还在于: 1.Fragment管理是在进程空间内的 2.Fragment的管理一般情况下是一个Window下进行的. Fragment的管理在一个进程空间内是比较好理解的,因为我们知道Activity的管理其实相对复杂,它的管理是通过IPC调用,IPC的一端是我们的Client,而作为Server的是Ams服务.Activity的管理是基于Window的,而Fr

Android群英传知识点回顾——第八章:Activity与Activity调用栈分析

8.1 Activity 8.1.1 起源 8.1.2 Activity形态 8.1.3 生命周期 8.2 Activity任务栈简介 8.3 ActivityManifest启动模式 8.3.1 standard 8.3.2 singleTop 8.3.3 singleTask 8.3.4 singleInstance 8.4 Intent Flag启动模式 8.5 清空任务栈 8.6 Activity任务栈使用 四大组件中出现频率最高的组件 Activity是与用户交互的第一接口,它提供了一

Intent 的Flag属性(Activity在栈位置的主宰者)

Intent 的Flag属性可用来控制Activity在栈中的排列位置,本文列举了常见的Flag. FLAG_ACTMTY_BROUGHT_TO_FRONT: 如特通过该Flag启动的Activity已经存在,下次再次启动时,将只是将该Activity带到前行.例如现存Activity栈中有Activity A,此时以该旗标启动Activity B(即Activity B是以FLAG_ACTMTY_BROUGHT_TO_FRONT旗标启动的),然后在Activity B中启动C.D,如果此时在A

Android apk动态加载机制的研究(二):资源加载和activity生命周期管理

出处:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (来自singwhatiwanna的csdn博客) 前言 为了更好地阅读本文,你需要先阅读Android apk动态加载机制的研究这篇文章,在此文中,博主分析了Android中apk的动态加载机制,并在文章的最后指出需要解决的两个复杂问题:资源的访问和activity生命周期的管理,而本文将会分析这两个复杂问题的解决方法.需要说明的一点是,我们不可能调起任何一个未安装的

activity调用栈

背景知识 Activity四种启动模式 标准模式 standard 栈顶复用模式 singleTop 栈内复用模式 singleTask 单例模式 singleInstance 任务栈 Activity的Flags Activity的Flags很多,这里介绍集中常用的,用于设定Activity的启动模式.可以在启动Activity时,通过Intent的addFlags()方法设置. (1)FLAG_ACTIVITY_NEW_TASK 其效果与指定Activity为singleTask模式一致.

使用adb shell dumpsys检测Android的Activity任务栈

谈起Android程序开发,就需要了解其四个主要的部件:Activity.Service.ContentProvider. BroadcastReceiver.而其中Activity是唯一直接控制程序界面呈现,直面用户操作的部件(当然BrowadCastReceiver也能通过桌面控件(App Widgets)来呈现有限的操作界面).Android对于Activity有严格的生命周期控制,以限制开发者在适当的回调函数里的放上合适的代码.对于多个Activity的转换,Android也有非常好的管