在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的任务栈

activity之栈管理的更多相关文章

  1. ActivityJump+ActivityManager【Activity之间的跳转和Activity任务栈管理】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 封装Activity跳转的方法以及实现Activity任务栈管理. 效果图   代码分析 ActivityJump:封装Activi ...

  2. 06 获取Activity的栈管理器

    代码 <span style="font-size:18px;">package com.fmy.day8_29task.util; import java.util. ...

  3. Activity 生命周期及其栈管理方式

    Activity 生命周期 Android 系统用栈的形式管理 Activity , 当新的 Activity 被创建是, 会被放置到栈顶, 这个 Activity 会进入到运行状态, 而前一个 Ac ...

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

    Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命 ...

  5. Android解析ActivityManagerService(二)ActivityTask和Activity栈管理

    前言 关于AMS,原计划是只写一篇文章来介绍,但是AMS功能繁多,一篇文章的篇幅远远不够.这一篇我们接着来学习与AMS相关的ActivityTask和Activity栈管理. 1.ActivitySt ...

  6. activity栈管理的3种方式

    一.背景 在android开发过程最经常使用的组件非activity莫属. 通过分析activity的各种跳转,执行同学能够分析用户的各种行为.更重要的一点是在做插件化的过程中,我们经常会对activ ...

  7. Android群英传》读书笔记 (4) 第八章 Activity和Activity调用栈分析 + 第九章 系统信息与安全机制 + 第十章 性能优化

    第八章 Activity和Activity调用栈分析 1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重 ...

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

    1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重新回到前台状态的时候会先调用onRestart方法,然 ...

  9. 安全退出app,activoty栈管理

    前言 由于一个同学问到我如何按照一个流程走好之后回到首页,我以前看到过4个解决方案,后来发现有做个记录和总结的必要,就写了这篇博文.(之前看小强也写过一篇,这里通过自身的分析完整的总结一下以下6种方案 ...

随机推荐

  1. SQLLoader4(数据文件中的列与表中列不一致情况-filler)

    A.数据文件中字段个数少于表中列字段个数,但数据文件中缺少的列,在表定义中可以为空.----- 这种情况是比较简单的,只需要将数据文件中数据对应的列的名字写到控制文件中即可.因为SQL*Loader是 ...

  2. 解决数据库Operation not allowed when innodb_forced_recovery > 0

    解决数据库Operation not allowed when innodb_forced_recovery > 0 请修改my.cnf innodb_force_recovery = 1 修改 ...

  3. android——仿微拍贷滑动圆形菜单

    一次偶然机会接触到微拍贷的app,瞬间被其圆形可滑动菜单吸引了.一直琢磨着给弄出来. 现在弄出来了.先看看效果吧 如果你也喜欢这个菜单.去我的github找源码吧.太忙了.没时间贴代码和讲解了. ht ...

  4. setNeedsDisplay、layoutSubViews

    UIView的setNeedsDisplay和setNeedsLayout方法.首先两个方法都是异步执行的.而setNeedsDisplay会调 用自动调用drawRect方法,这样可以拿到UIGra ...

  5. ActiveMQ持久化消息(转)

    ActiveMQ的另一个问题就是只要是软件就有可能挂掉,挂掉不可怕,怕的是挂掉之后把信息给丢了,所以本节分析一下几种持久化方式: 一.持久化为文件 ActiveMQ默认就支持这种方式,只要在发消息时设 ...

  6. jquery动态添加DOM节点

    1.append()方法:向每个匹配的元素内部添加元素 appendTo()方法:将所有匹配的元素追加的指定的元素中 <html> <head> <meta http-e ...

  7. (原)lua使用ffi调用c程序的函数

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5812763.html 参考网址: http://luajit.freelists.narkive.co ...

  8. 当nginx 500 伪静态错误时,记录解决方法rewrite or internal redirection cycle while processing

    错误日志::rewrite or internal redirection cycle while processing "/index.php/index.php/index.php/in ...

  9. Ubuntu安装字体的方法

    基本步骤如下: 1. 将要安装的字体放在一个文件夹下,以/home/UsrName/Download/Font为例 2.在终端中输入 sudo cp -r /home/UsrName/Download ...

  10. MySQL--mysqldump的权限说明

    mysqldump 所需要的权限说明: 1.对于table 来说mysqldump 最少要有select 权限. 2.对于view 来说mysqldump 要有show view 权限. 3.对于tr ...