Activity堆栈管理

task就好像是能包含很多activity的栈。 默认情况下,一个activity启动另外一个activity时,两个activity是放在同一个task栈中的,第二个activity压入第一个 activity所在的task栈。当用户按下返回键时,第二个activity从栈中弹出,第一个activity又在当前屏幕显示。这样,从用户角度来看,这两个activity就好像是属于同一个应用程序的,即使第二个activity是属于另外一个应用程序的。当然,这是指默认情况下。 task栈包含的是activity的对象。如果一个activity有多个实例在运行,那么栈中保存的是每个实例的实体。栈中的activity不会重新排列,只有弹出和压入操作。 一个task中的所有activity都以整体的形式移动。整个task可以被移到前台或后台。打个比方,当前的task包含4个activity–当前 activity下面有3个activity。当用户按下HOME键返回到程序启动器(application launcher)后,选择了一个新的应用程序(事实上是一个新的task),当前的task就被转移到后台,新的task中的根activity将被显示在屏幕上。过了一段时间,用户按返回键回到了程序启动器界面,选择了之前运行的程序(之前的task)。那个task,仍然包含着4个 activity。当用户再次按下返回键时,屏幕不会显示之前留下的那个activity(之前的task的根activity),而显示当前 activity从task栈中移出后栈顶的那个activity。 刚刚描述的行为是默认的activity和task的行为。有很多方法能够改变这种行为。activity和task之间的联系,以及task中的 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

默认情况下,一个应用程序中的所有activity都有一个affinity–这让它们属性同一个task。然而,每个activity可以通过<activity>中的taskAffinity属性设置单独的affinity。不同应用程序中的activity可以共享同一个 affinity,同一个应用程序中的不同activity也可以设置成不同的affinity。affinity属性在2种情况下起作用:当启动 activity的Intent对象包含FLAG_ACTIVITY_NEW_TASK标记,或当activity的 allowTaskReparenting被设置成true。FLAG_ACTIVITY_NEW_TASK 标记

当传递给startActivity()的Intent对象包含 FLAG_ACTIVITY_NEW_TASK标记时,系统会为需要启动的activity寻找与当前activity不同的task。如果要启动的 activity的affinity属性与当前所有的task的affinity属性都不相同,系统会新建一个带那个affinity属性的task,并将要启动的activity压到新建的task栈中;否则将activity压入那个affinity属性相同的栈中。

allowTaskReparenting属性

如果一个activity的allowTaskReparenting属性为true,那么它可以从一个task(TASK1)移到另外一个有相同affinity的task(TASK2)中(TASK2带到前台时)。

如果一个.apk文件从用户角度来看包含了多个“应用程序”,你可能需要对那些 activity赋不同的affinity值。

运行模式

activity的launchMode属性可以有四种值:

  • standard ” (默认)
  • singleTop “
  • singleTask “
  • singleInstance “

这4种模式可以按4种分类来区分,以下假设位于task1中的activity1启动activity2:

模式/分类 包容activity2的task 一个activity是否允许有多个实例 activity是否允许有其它activity共存于一个task 对于新的intent,是否总是实例化activity对象
standard 如果不包含FLAG_ACTIVITY_NEW_TASK标记,则activity2放入 task1,否则按前面讲述的规则为activity2选择task 可被多次实例化,同一个task的不同的实例可位于不同的task中,每个task也可包含多个实例 允许 是的。当接收到新的intent时,总是会生成新的activity对象。
singleTop 同standard 同standard 允许 已存在的activity对象,如果位于目标task的栈顶,则该activity被重用,如果它不位于栈顶,则会实例化新的activity对象
singleTask 将activity2放到task1栈底 不能有多个实例。由于该模式下activity总是位于栈顶,所以actvity在同一个设备里至多只有一个实例 允许。singleTask模式的activity总是位于栈底位置。目标activity 实例已存在时,如果该实例刚好位于task栈顶,则接收intent,否则到来的intent将会被丢弃,但该可以响应该intent的那个 activity所在的task将会被移到前台。  
singleInstance 同singleTask 同singleTask 不允许与其它activity共存于一个task。如果activity1的运行在该模式下,则activity2一定与activity1位于不同的task  

对于新到的intent,如果是由新创建的activity对象来接收,则用户可以通过返回键回到之前的activity;如果是由已存在的 activity来接收,则用户无法通过返回键返回到接收intent之前的状态。

清空栈

当用户长时间离开task(当前task被转移到后台)时,系统会清除task中栈底activity外的所有activity。这样,当用户返回到task时,只留下那个task最初始的activity了。

这是默认的情况,<activity>中有些属性可以改变这种行为。

alwaysRetainTaskState属性

如果栈底activity的这个属性被设置为true,刚刚描述的情况就不会发生。 task中的所有activity将被长时间保存。

clearTaskOnLaunch属性

如果栈底activity的这个属性被设置为true,一旦用户离开task,则 task栈中的activity将被清空到只剩下栈底activity。这种情况刚好与alwaysRetainTaskState相反。即使用户只是短暂地离开,task也会返回到初始状态(只剩下栈底acitivty)。

finishOnTaskLaunch属性

这个属性与clearTaskOnLaunch相似,但它只对单独的activity操作,而不是整个task。它可以结束任何activity,包括栈底的activity。当它设置为true时,当前的activity只在当前会话期间作为task的一部分存在,当用户退出activity再返回时,它将不存在。

另外还有一种方法能将activity强行从stack中移出。如果intent对象包含FLAG_ACTIVITY_CLEAR_TOP 标记,当目标task中已存在与接收该intent对象的 activity类型相同的activity实例存在时,所有位于该activity对象上面的activity将被清空,这样接收该intent的 activity就位于栈顶,可以响应到来的intent对象。如果目标activity的运行模式为standard,则目标activtiy也会被清空。因为当运行模式为standard时,总会创建新的activity对象来接收到来的intent对象。

FLAG_ACTIVITY_CLEAR_TOP标记常常和FLAG_ACTIVITY_NEW_TASK一起使用。用2个标记可以定位已存在的 activity并让它处于可以响应intent的位置。

启动任务(Task)

Intent filter中有”android.intent.action.MAIN ” action和”android.intent.category.LAUNCHER ” category的activity将被标记为task的入口。带有这两个标记的activity将会显示在应用程序启动器(application launcher)中。

第二个比较重要的点是,用户必须能够离开task并在之后返回。因为这个原因,singleTask和singleInstance这两种运行模式只能应用于含有MAIN和LAUNCHER过滤器的 activity 。打个比方,如果不包含带MAIN和LAUNCHER过滤器,某个activity运行了一个singleTask模式的 activity,初始化了一个新的task,当用户按下HOME键时,那个activity就被主屏幕“挡住”了,用户再也无法返回到那个 activity。

类似的情况在FLAG_ACTIVITY_NEW_TASK标记上也会出现。如果这个标记会新建一个task,当用户按下HOME键时,必须有一种方式能够让用户返回到那个activity。有些东西(比如notification manager)总是要求在外部task中启动activity,在传递给startActivity的intent中总是包含 FLAG_ACTIVITY_NEW_TASK标记。

对于那种不希望用户离开之后再返回activity的情况,可将finishOnTaskLaunch属性设置为true。

时间: 2024-08-26 14:59:04

Activity堆栈管理的相关文章

Android4.4 framework分析——ActivityManagerService的启动和对Activity的管理

本文主要介绍android4.4中ActivityManagerService的启动和ActivityManagerService对Activity堆栈的管理. 一.ActivityManagerService的启动 ActivityManagerService也是在SystemServer启动的时候创建的, <span style="font-size:18px;">class ServerThread { .......   public void initAndLoo

activity栈管理的3种方式

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

Managing the Activity Lifecycle 管理活动的生命周期

Managing the Activity Lifecycle 管理活动的生命周期 Previous         Next         Get started Dependencies and prerequisites 依赖和先决条件 How to create an Android project (see Creating an Android Project) 如何创建一个Android项目(参见创建一个Android项目) You should also read 你也应该阅读

Android使用adb获得activity堆栈信息

非常有用的命令: adb shell dumpsys activity 该命令可以看到当前运行的是哪个activity,运行的一些进程等 首先可以看到运行的进程: ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes) Process LRU list (sorted by oom_adj, 43 total, non-act at 1, non-svc at 1): PERS #42: sys F/ /P trm: 0 8

History API与浏览器历史堆栈管理

阅读目录 History API回顾 History API与业务实践 回顾 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash值进行路由,这种实现不存在兼容性问题,但是缺点也有--针对不支持onhashchange属性的IE6-7需要设置定时器不断检查hash值改变,性能上并不是很友好. 而如今,在移动端开发中HTML5规范给我们提供了一个History接口,使用该接口可以自由操纵历史记录.本文并不详细介绍Hi

【转】Android 之ActivityThead、ActivityManagerService 与activity的管理和创建

在android中,Activity是四大组件中比较重要的一个(当然其他的也比较重要),那么android中是怎样管理这些activity的?应用的进程和主线程是怎么创建的,应用的消息循环又是在什么时候创建的?在这篇文章中将详细介绍: 先来看下涉及到的类,通过以下类图对整体先有个大概的印象: ActivityThread: ActivityThread主要用来启动应用程序的主线程,并且管理在应用端跟用户打交道的activity.在应用端的activity信息全部被存储在ActivityThrea

清理Activity堆栈

1 Intent intentBack = new Intent(this, MainActivity.class); 2 intentBack.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//通过设置intent的flag来切断跳转的去得activity和前世的所有纠葛 3 startActivity(intentBack);

java-重载、包修饰词以及堆栈管理

1.方法的重写(Override):重新写.覆盖 1)发生在父子类中,方法名称相同,参数列表相同,方法体不同 2)重写方法被调用时,看对象的类型2.重写与重载的区别: 1)重写(Override): 1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同 1.2)遵循"运行期绑定",看对象的类型来调用方法 (最后附带举例说明) 2)重载(Overload): 2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同 2.2)遵循"编译期绑定",看引用的

关于安卓的activity task管理

一.Activity和Task(栈)的关系 Task就像一个容器,而Activity就相当与填充这个容器的东西,第一个东西(Activity)则会处于最下面,最后添加的东西(Activity)则会在最低端.从Task中取出东西(Activity)则是从最顶端取出,也就是说最先取出的是最后添加的东西(Activity),一次类推,最后取出的是第一次添加的Activity,而Activity在Task中的顺序是可以控制的,那则在Activity跳转时用到Intent Flag 二.界面跳转和服务的启