`
George_ghc
  • 浏览: 93040 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Activity和Task的基本模型

阅读更多
【转:】http://hubingforever.blog.163.com/blog/static/17104057920101194575866/

一个Activity可以启动另一个,即便是定义在不同应用程序中的Activity。例如,假设你想让用户显示一些地方的街景。
而这里已经有一个Activity可以做到这一点,因此,你的Activity所需要做的只是在Intent对象中添加必要的信息,并传递给startActivity()。
地图浏览将会显示你的地图。当用户按下BACK键,你的Activity会再次出现在屏幕上。
对于用户来说,看起来好像是地图浏览与你的Activity一样,属于相同的应用程序,即便是它定义在其它的应用程序里,并运行在那个应用程序的进程里。
Android通过将这两个Activity保存在同一个Task里来体现这一用户体验。简单来说,一个Task就是用户体验上的一个“应用”。
它将相关的Activity组合在一起,以stack的方式管理。用Activity启动Task的一典型就是用户在应用程序启动栏中选择一个Activity。
位于stack顶端的Activity是当前正在运行的——能够聚焦用户的动作。当一个Activity启动另一个新的Activity进入stack;它成为正在运行的Activity。
之前的Activity仍保留在stack中。当用户按下BACK键,当前的Activity从stack中退出,之前的那个成为正在运行的Activity。
注意1:一个task并不是对应一个线程,实际上一个task可以包含多个进程。
  一个Task中可能有多个同一个Activity的实例时(如多个地图浏览)。
一个Task就是一组Activity,不是一个类或者在manifest中定义的一个元素。Task的属性值是由根Activity决定的(即由Task的第一个Activity设置)。例如Task的“affinity”;那个值就是从Task中的根Activity中读取的。
Task中的所有Activity作为一个单元一起移动。整个Task(整个Activity stack)可以进入前台或者退到后台。
例如,假设当前Task中的stack中有4个Activity——3个位于当前Activity下方。用户按下HOME键,进入到应用程序启动栏,
然后选择一个新的应用程序(实际上,一个新的Task)。当前Task退到后台,并且新Task中的根Activity会显示出来。
然后,经过一段时间后,用户回到Home画面,然后再次选择前一个应用程序(前一个Task)。
那个拥有4个Activity的Task会进入前台。当用户按下BACK键,屏幕不会显示用户刚刚离开的Activity(前一个Task的根Activity)。
而是,这个stack中的顶端Activity移除,相同Task中的前一个Activity会显示出来。
  刚才描述的行为是Activity和Task的默认行为。但有方法来完全改变它。Task之间的关联和Task中的Activity行为,受启动Activity的Intent对象中设置的Flag和manifest文件中Activity的<activity>元素的特性值交互控制。调用者和响应者都有权决定如何发生。
注意:可以在Activity中通过getTaskId()得到它所在task的Id
核心的Intent Flag有:
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
接下来的将描述一些Flag和特性的用法,如何相互影响,以及在使用时的建议。
Affinity和新Task
默认情况下,一个应用程序中(APK)的所有Activity都有相同的affinity(即manifest中的package名)
然而,每个Activity都可以在<activity>元素的taskAffinity特性上设置单独的值。
例如:
        <activity android:name=".HelloActivity"
                  android:label="@string/app_name"
                  android:taskAffinity="com.teleca.robin.taskAffinity1">>
                        <intent-filter>
                <action android:name="com.teleca.robin.Hello" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
在程序中可以通过如下的方式得到:
        Intent mainIntent = new Intent("com.teleca.robin.Hello", null);
        mainIntent.addCategory("android.intent.category.DEFAULT");
        List<ResolveInfo> apps;
        apps = getPackageManager().queryIntentActivities(mainIntent, 0);
        if(apps==null)
            System.out.println("no acitivity is find");
        for(int i=0;i<apps.size();i++)
        {
            ActivityInfo a=apps.get(i).activityInfo;
            System.out.println(a.name+" taskAffinity:"+a.taskAffinity);
        }
判断是否是Task的根和得到taskId可以Activity的isTaskRoot()方法和getTaskId()用如下的方法:
text.setText("is TaskRoot:"+isTaskRoot()+"this is the No "+(id++)+"Hello"+"task id:"+this.getTaskId());
定义在不同应用程序中的Activity可以共享同一个affinity,或者定义在同一个应用程序中的Activity设置不同的affinity。
Affinity在两种环境下工作:Intent对象包含FLAG_ACTIVITY_NEW_TASK标志,和Activity的allowTaskReparenting特性设置为“true”。
核心的Intent Flag
FLAG_ACTIVITY_NEW_TASK:
        一个Activity一般通过调用startActivity()启动并加入到Task中。它同调用者一样,进入同一个Task。
然而,如果传递给startActivity()的Intent对象中包含FLAG_ACTIVITY_NEW_TASK时,系统会搜索一个新的Task来容纳新的Activity。
通常,如标志的名字所示,是一个新的Task。然而,并不是必须是。如果已经存在一个Task与新Activity的affinity相同,这个Activity就会加入到那个Task中。如果不是,启动一个新的Task。
如果启动它的acitve和新Activity的affinity相同,那么新Activity的会进入启动它的acitve所在的Task.
核心的<activity>特性:
allowTaskReparenting:
如果一个Activity的allowTaskReparenting特性设置为“true”,它就能从启动的Task中移到有着相同affinity的Task(这个Task进入到前台的时候)。
例如,在一个旅游的程序中定义了一个可以报告选择城市的天气情况的Activity。它和同一个应用程序的其它Activity一样,有着相同的Affinity(默认的Affinity),并且它允许重新宿主。
你的Activity中的一个启动了天气预报Activity,因此,它初始化到和你Activity相同的Task中。
如果旅游应用程序当前没被启动,那么下次它被启动时,天气预报那个Activity将会被显示(即在旅游应用程序的Task中被显示)。
如果从用户的角度出发,一个.apk文件包含多个“应用”的话,你可能希望为关联的Activity设置不同的affinity。
Launch Mode
这里4种不同的启动模式可以设置到<activity>元素的launchMode特性上:
standard(默认模式)
singleTop
singleTask
singleInstance
注意1:对于singleTask,如果新的Activity和旧的Activity的affinity一样时,这时它相当于FLAG_ACTIVITY_NEW_TASK。
注意2:对于singleTask和singleInstance的affinity最好不要和别的task的affinity相冲突。
这些模式有以下四点区别:
1,  哪个Task将容纳响应Intent的Activity。
    对于“standard”和“singleTop”来说,除非Intent对象包含FLAG_ACTIVITY_NEW_TASK,那么新的Activity在是产生Intent的那个Task中(并调用startActivity())。
  对于“singleTask”来说,如果它的taskAffinity属性和启动它Activity的一样的话,那么它是产生在启动它Activity的Task中(并调用startActivity()),否则它是产生在新Task中,且是该Task的根
    对比而言,“singleInstance”指示Activity总是一个Task的根。
系统会重新创建一个Task,并把新的Activity加入其中,它们不会加入到另一个Task中。
2,  是否有多个Activity的实例。“standard”和“singleTop”可以实例化多次。它们可以属于多个Task,一个特定的Task可以有相同Activity的多个实例。
    对比而言,“singleTask”和“singleInstance”只能有一个实例。不可能在多个task中同时存在有该Activity的多个实例。
    也不可能在一个task中存在有该Activity的多个实例。
3,是否可以在同一个Task中拥有其它的Activity。“singleInstance”Activity保持单身,在它的Task中它是仅有的Activity。
    如果它启动另一个Activity,那个Activity将会放入到不同的Task中,而不管它的启动模式——好像FLAG_ACTIVITY_NEW_TASK在Intent中一样。
    其它三个模式允许多个Activity加入到这个Task中。
4, 是否一个新的实例启动来处理新的Intent。对于默认的“standard”来说,都是创建一个新的实例来响应新的Intent。每个实例处理一个Intent。
对于“singleTop”来说,如果它位于目标Task的顶端,那么,已经存在的实例就可以重复使用来处理这个新的Intent。
如果它不在顶端,那么它就不能重复使用。替代的,新的实例将创建来响应新的Intent,并进入到stack中。
例如,假设一个Task的Activity stack中包含根Activity A和其它Activity B,C,D,并且D位于顶端,因此,stack是A-B-C-D。有一个Intent来了,它要启动D类型的Activity。如果D有默认的“standard”启动模式,那么一个新的实例将被启动并且stack变成A-B-C-D-D。
然而,如果D的启动模式“singleTop”,已经存在的实例将去处理新来的Intent(因为它正好处在stack的顶端),并且stack依旧是A-B-C-D。
换句话说,如果来临的Intent是冲着B类型的,那么,B类型的实例将被创建启动而不管B的模式是“standard”或“singleTop”(因为B不处在stack的顶端),
因此,stack将会是A-B-C-D-B。
  之前提到的,设备上不会出现超过一个实例的“singleTask”或“singleInstance”Activity,因此,那个实例都将去处理所有新来的Intent。
“singleInstance”Activity总是位于stack的顶端(因为它是task中唯一的Activity),因此,它总是处于能处理Intent的位置。
“singleTask”Activity可能有或没有其它Activity处于它的上方,它可能是根,也可能不是根。如果它的android:taskAffinity和启动它的acitivity的android:taskAffinity不一样,它就总是位于Activity stack的底部,它就是根,如果一样,它就不是位于Activity stack的底部,它就不是根。如果在它上方有activity,而这时来个启动该“singleTask”Activity的Intent,那么是该Activity处理该Intent,而不是它上方的Activity。这时上方的所有Activity会被清除掉,当然也Destroy。
如果在它上方有activity,而这时来个启动其上方的某个Activity的Intent,那么是上方的Activity处理该Intent,而不是该“singleTask”Activity。
    当一个存在的Activity请求去处理一个新的Intent时,Intent对象将传到该Activity的onNewIntent()的方法中。(原来启动Activity的Intent对象可以通过调用getIntent()得到。)
注意:当一个新的实例创建来处理新的Intent时,用户可以按下BACK键返回到之前的状态(前一个Activity)。
但一个存在的实例来处理新的Intent时,用户不能按下BACK键返回到新Intent到来之前当前Activity的状态,它也是返回前一个Activity。
stack的清除
    如果用户离开Task很长一段时间,系统会清除Task中的所有Activity,除根Activity外。当用户再次返回到这个Task时,和用户离开时不一样,仅仅只是初始化Activity呈现。
    这样做的意图是,经过一些时间后,用户可能已经忘记之前正在做的事情,并且打算回到Task开始些新的时期。
注意1:弹出任务管理器不算离开Task
这是默认情况。下面一些Activity特性可以用于控制这一行为并且修改它:
alwaysRetainTaskState:
如果Task的根Activity的这个特性设置为“true”时,上面描述的默认行为不会发生。Task保留所有的Activity,即便是经过很长一段时间。
clearTaskOnLaunch:
如果Task的根Activity的这个特性设置为“true”时,当用户离开Task并返回时,stack会清除直到根Activity。换句话说,它是alwaysRetainTaskState的另一个极端。用户总是回到Task的初始化状态,即便是一个短暂的离开。
finishOnTaskLaunch:
这个特性和clearTaskOnLaunch相似,但它针对单个Activity,不是整个Task。它能使除了根Activity之外的任何Activity消失。
当它设置为“true”时,这个Activity仅在当前会话期间保持为Task的部分。如果用户离开并再次返回到这个Task,它就不再显示了。
注意:对于clearTaskOnLaunch和finishOnTaskLaunch所谓的清除总是在该task被再次启动时执行的。
这里还有其它的方式可以强制Activity从stack中移除。如果Intent对象中包含FLAG_ACTIVITY_CLEAR_TOP标志,并且目标Task中已经有一个这个类型Activity的实例,
而且这个实例应该处理这个Intent,那么,位于其上的Activity都将移除,这样,这个Activity就能在stack的顶端并响应这个Intent。
如果这个Activity的启动模式设定为“standard”,它也会从stack中清除,然后新的实例启动来响应这个Intent。
这是因为当启动模式设定为“standard“时,总是会创建一个新的实例来响应新的Intent。
FLAG_ACTIVITY_CLEAR_TOP经常与FLAG_ACTIVITY_NEW_TASK结合起来使用。当一起使用时,这些标志可以定位其它Task中已经存在的Activity,并且把它置于可以响应Intent的位置。
启动Task
如果一个Activity的Intent Filter的action为“android.intent.action.MAIN”、category为“android.intent.category.LAUNCHER”时,
它就可以作为一个Task的入口点。有这种类型的Filter会在导致这个Activity在应用程序启动栏显示一个图标和标签,给用户提供一个方式可以启动这个Task和在任何时候可以再次回到这个Task。
第二个能力很重要:用户一定可以离开一个Task,然后可以再次回到它。
基于这个原因,“singleInstance”应该只在有MAIN和LAUNCHER的Activity上使用。
“singleTask”在没有MAIN和LAUNCHER的Activity上使用,应该让它和入口Activity(有MAIN和LAUNCHER的Activity)的taskAffinity一致
例如,假设这个Filter没有且它和入口Activity的taskAffinity又不一致的话:一个Intent启动了一个“singleTask”Activity,初始化一个新的Task,然后用户花费了一些时间在它上面。然后,用户按下HOME键。现在,这个Task处于后台并且被HOME画面遮盖。
由于它不能在应用程序启动栏显示,用户就没有办法可以返回它。
注意1:弹出任务管理器不算离开Task。
注意2:应用程序启动的只是个Task,如果“singleInstance”的Activity没这个Intent Filter的话,自然不能在离开后返回到它。如果“singleTask”的Activity没这个Intent Filter的且它和入口Activity的taskAffinity又不一致的话,自然不能在离开后返回到它.
在面对FLAG_ACTIVITY_NEW_TASK时,也有相似的困难。如果这个标志导致一个Activity启动了一个新的Task,并且用户按下HOME键离开它,这里必须有方法可以再次回到它。
一些机能(如Notification Manager)总是在外部的Task中启动Activity,而不是作为自己的一部分,因此,它总是把FLAG_ACTIVITY_NEW_TASK标志放入Intent,然后传递给startActivity()。
如果你的Activity可能会被外部的机能(可能使用这个标志)调用,注意用户可以额外的方式可以返回到启动的Task。
如果你不想用户回到某个Activity,可以把<activity>元素的finishOnTaskLaunch设置为“true”。
非Activity Context启动Activity
    对于Context的startActivity方法,如果不是在其子类(Activity)中调用,那么必须对Intent加上FLAG_ACTIVITY_NEW_TASK。
具体可以参照Context中对startActivity方法的说明:
public void startActivity (Intent intent)
    Launch a new activity. You will not receive any information about when the activity exits.
Note that if this method is being called from outside of an Activity Context,
then the Intent must include the FLAG_ACTIVITY_NEW_TASK launch flag. This is because, without being started from an existing Activity, there is no existing task in which to place the new activity and thus it needs to be placed in its own separate task.
This method throws ActivityNotFoundException if there was no Activity found to run the given Intent.
Parameters
intent     The description of the activity to start.
分享到:
评论

相关推荐

    Android Task 进程与线程详解

    在 Android 中,每一个 Activity 的 Task 模式,都是可以由 Activity 提供方(通过配置文件)和 Activity 使用方(通过 Intent 中的 flag 信息)进行配置和选择。使用方对 Activity 的控制力,是限定在提供方允许的...

    042集-跨进程启动Activity和设置Activity多个入口

    在Android开发中,进程是应用程序运行的基本单位,而Activity作为用户界面的核心组件,通常与特定的进程关联。本集视频“042集-跨进程启动Activity和设置Activity多个入口”将深入探讨如何在不同进程中启动Activity...

    Android基础系列的Activity

    理解和熟练掌握Activity的生命周期、Intent的使用、Activity间的通信、栈管理、多窗口支持、Activity过渡动画以及配置变化处理,是Android开发者的基本功。通过深入学习和实践,可以创建出更加高效、用户友好的应用...

    activity工作流 小项目

    1. **活动(Activity)**:是工作流中的基本单元,代表了一个具体的任务或操作。 2. **流程定义(Process Definition)**:描述了整个业务流程,包括各个活动的顺序、条件、分支等。 3. **流程实例(Process ...

    Android应用源码之模拟Activity进出栈.zip

    在Android系统中,Activity的启动和切换遵循着一个称为"任务(Task)"和"回退栈(Back Stack)"的模型,这使得用户可以按后进先出(LIFO)的顺序操作活动。 首先,理解Activity的生命周期至关重要。Activity有多种...

    activity工作流demo

    例如,可能有"workflow_instance"表来存储每个工作流程实例的信息,"task"表来保存每个任务的详细信息,以及"participant"表来管理流程中的角色和用户。此外,还有可能包含一些视图或触发器,用于简化查询或自动执行...

    activity-5.22.0的源码包

    它提供了一套完整的流程定义和执行模型,支持BPMN 2.0标准,使得开发者能够通过图形化方式设计复杂的业务流程,并将其转换为可执行的代码。在5.22.0版本中,Activity进一步优化了性能,增强了稳定性,并修复了一些...

    activity 生命周期 demo

    Android的Task和Activity栈模型确保了Activity的正确管理。当启动一个新Activity时,它会被压入当前Task的栈顶,而前一个Activity则留在栈底。用户通过返回键会依次关闭栈顶的Activity,直至回到栈底。 五、Intent...

    比较全面的activity5使用手册

    主要概念包括流程定义(Process Definition)、流程实例(Process Instance)、任务(Task)和事件(Event)。流程定义是静态的业务流程模型,而流程实例是流程定义在运行时的动态表示。 2. **Activiti数据库表结构...

    android activity研究

    本文将深入探讨 `Activity` 的基本概念及其配置参数,并对 `Intent`、`TaskAffinity` 和 `Launch Mode` 进行详解。 #### 二、Activity 基础概念 **1. Activity 定义:** - **定义**:`Activity` 可以理解为一个...

    关于高斯混合模型(GMM)的论文集

    例如,"2000-Learning Patterns of Activity Using Real-Time Tracking"这篇论文可能涵盖了如何利用实时追踪技术来识别和学习人类活动的模式,其中GMM可能被用作模型来捕捉不同活动的动态变化。引用次数高达480次,...

    activity源码

    3. **执行模型**:在运行时,Activiti使用`Execution`和`Task`对象来表示流程实例和任务。这些对象在`RuntimeService`和`TaskService`中被创建、更新和删除,它们在`ExecutionEntity`和`TaskEntity`中具有对应的...

    初中级Android开发社招面试之Activity篇.zip

    Activity的栈管理模型(任务栈Task Stack)也是面试官关注的点。Android使用后进先出(LIFO)的栈来管理Activity,遵循“回退栈”原则。当用户按回退键,栈顶的Activity会被销毁,呈现上一个Activity。理解FLAG_...

    android开发activity跳转

    5. **栈管理与生命周期**:Android系统使用任务(Task)和堆栈(BackStack)模型管理Activity。每次启动新Activity时,它都会被压入栈顶。按返回键会从栈顶弹出最近的Activity,遵循“后进先出”原则。因此,理解...

    工作流模型分析

    首先,活动(Activity)是工作流模型的基本元素,它代表流程中的一个逻辑步骤,可以是一次操作或一系列操作的集合。任务(Task)则是流程需要完成的具体工作,它可以是一个简单的操作,也可以是多个操作的组合。在...

    Eclipse 插件 离线安装 Activity Bpmn 2.0 Designer-5.18.0全部包

    - **流程建模**:通过拖拽和放置,你可以创建复杂的BPMN流程图,包括任务(Task)、网关(Gateway)、事件(Event)和泳道(Lane)等元素。 - **属性编辑**:每个BPMN元素都可以配置详细的属性,例如任务类型、条件...

    工作流模型分析.pptx

    工作流模型是组织内部自动化处理任务的关键工具,它定义了工作流程的结构和逻辑,确保了业务过程的有效管理和执行。本文件"工作流模型分析.pptx"详细介绍了多种常见工作流模型及其特点,包括任务与活动、流程起点、...

    基于activity工作流产品规划

    ### 基于Activity工作流产品规划的知识点详解 #### 一、Activiti项目概述 - **背景**:Activiti项目作为一个新兴的开源业务流程管理(Business Process Management, BPM)平台,采用Apache许可协议,专注于支持最新...

    Activity6.0 中文用户手册HTML

    在 Activiti 中,流程定义主要通过流程模型(Process Definition)来完成,这通常涉及创建一个XML文件,其中包含了流程的各个元素,如任务(Task)、事件(Event)、网关(Gateway)等。用户手册将详细讲解如何使用...

Global site tag (gtag.js) - Google Analytics