`
zhaohaolin
  • 浏览: 1011619 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Android开发之旅:活动与任务

阅读更多

Android开发之旅:活动与任务

 ——坚持就是胜利!关键是你能坚持吗?不能的话,你注定是个失败者。

引言

关于Android应用程序原理及术语,前面两篇:

介 绍了Android应用程序的进程运行方式:每一个应用程序运行在它自己的Linux进程中。当应用程序中的任何代码需要执行时,Android将启动进 程;当它不在需要且系统资源被其他应用程序请求时,Android将关闭进程。而且我们还知道了Android应用程序不像别的应用程序那样(有Main 函数入口点),它没有单一的程序入口点,但是它必须要有四个组件中的一个或几个:活动(Activities) 、服务(Services) 、广播接收者(Broadcast receivers) 、内容提供者(Content providers)。且分别介绍它们的作用,及如何激活和关闭它们、如何在清单文件(AndroidManifest.xml)中声明它们及 Intent过滤器。

在简单回顾之后,本篇还是继续介绍Android应用程序原理及术语——活动与任务(Activities and Tasks)。

  • 1、活动与任务概述
  • 2、亲和度和新任务(Affinities and new tasks)
  • 3、启动模式(Launch modes)
  • 4、清除栈(Clearing the stack)
  • 5、启动任务(Starting tasks)

1、活动与任务概述

如前所述,一个活动(activity)能启动另一个活动,包括定义在别的应用程序中的活动。再次举例说明,假设你想让用户显示某地的街道地图。而且已经有了一个活动能做这个事情(假设 这个活动叫做地图查看器),因此你的活动要做的就是将请求信息放进一个Intent对象,然后将它传给startActivity() 。地图查看器就启动并显示出地图。当用户点击返回按钮之后,你的活动就会重新出现在屏幕上。

对用户来说,这个地图查看器就好像是你的应用程序的活动一样,虽然它定义在其他的应用程序中且运行在那个应用程序的进程中。Android将这些活动保持在同一个任务task )中以维持用户的体验。简单地讲,任务是用户体验上的一个“应用程序”,是排成堆栈的一组相关活动 。 栈底的活动(根活动)是起始活动——一般来讲,它是用户在应用程序启动器(也称应用程序列表,下同)中选择的一个活动。栈顶的活动是正在运行的活动——它 关注用户的行为(操作)。当一个活动启动另一个,新的活动被压入栈顶,变为正在运行的活动。前面那个活动保存在栈中。当用户点击返回按钮时,当前活动从栈 顶中弹出,且前面那个活动恢复成为正在运行的活动。(关于栈的先进后出 特性不要我在这里讲吧!)

栈中包含对象,因此如果一个活动(再次说明:活动是Activity的子类 ) 启动了多个实例——例如多个地图查看器,则栈对每个实例有一个独立的入口。(可以这样理解:假设有四个活动以这样的顺序排在栈中——A-B-C-D,现在 又有一个C的实例,则栈变成A-B-C-D-C,这两个C的实例是独立的。)栈中的活动从不会被重新排列,只会被压入、弹出。这点很好理解,因为活动的调 用顺序是固定的。

任务是一栈的活动,而不是清单文件中声明的某个类或元素,因此无法独立于它的活动为任务赋值。整个任务的值是在栈底活动(根活动)设置的。例如,下节将讨论的“任务亲和度”,亲和度信息就是从任务的根活动中获取的。

一 个任务的所有活动作为一个整体运行。整个任务(整个活动栈)可置于前台或发送到后台。例如,假设当前任务有四个活动在栈中——三个活动在当前活动下面。用 户按下HOME键,切换到程序启动器,并选择一个新的应用程序(实际上是一个新的任务)。当前任务进入后台,新任务的根活动将显示。接着,过了一会,用户 回到主屏幕并再次选择之前的应用程序(之前的任务)。那个任务栈中的所有四个活动都变为前台运行。当用户按下返回键时,不是离开当前任务回到之前任务的根 活动。相反,栈顶的活动被移除且栈中的下一个活动将显示。

上面所描述的是活动和任务的默认行为,但是有方法来改变所有这些行为。活动与任务之间的联系及任务中活动的行为,是由启动活动的Intent 对象的标志(flags)和清单文件中活动<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

接下来的小节将讨论这些标志和属性的作用,他们怎么交互,及使用的注意事项。

2、亲和度和新任务(Affinities and new tasks)

默认情况下,一个应用程序的所有活动互相之间都有一个亲和度(affinity ——也就是说,他们属于同一个任务的偏好(preference)。然而,也可以通过<activity> 元素的taskAffinity 属性为每个活动设置个体亲和度。定义在不同应用程序中的活动能够共享亲和度,同一个应用程序中的活动可以分配不一样的亲和度。亲和度发挥作用的两种情况:1)启动活动的Intent 对象包含FLAG_ACTIVITY_NEW_TASK 标志时;2)一个活动的allowTaskReparenting 属性为"true "时。

  • FLAG_ACTIVITY_NEW_TASK 标志

如前所述,默认情况下,一个新的活动被启动到调用startActivity() 方法的活动所在的任务。它被压入调用它的活动的栈中。但是,如果传递给方法的Intent 对象包含FLAG_ACTIVITY_NEW_TASK 标志,系统找一个不同的任务容纳活动。通常,顾名思义它表示一个新任务。但是,他并非一定如此。如果已经存在一个任务与新活动亲和度一样,该活动将启动到该任务。如果不是,则启动一个新任务。

  • allowTaskReparenting 属性

如果一个活动的allowTaskReparenting 属性为"true ", 它可以从启动它的任务转移到与它有亲和度并转到前台运行的任务中。例如,假设一个天气预报的活动,但选择城市是一个旅游应用程序的一部分。它与同一个应用 程序中的其他活动具有相同的亲和度,且允许重新选择父活动(reparenting)。你的一个活动启动天气预报活动,因此他初始是跟你的活动属于同一个 任务。但是,当旅游应用程序切换到前台运行时,天气预报活动将被重新分配和显示到该任务。

如果一个.apk文件,从用户的角度看包含不止一个“应用程序”,你可能要为与他们有关的些活动指定不一样的亲和度。

3、启动模式(Launch modes)

有四种不同的启动模式可以分配到<activity> 元素的launchMody 属性:

  • "standard "(默认模式)
  • "singleTop "
  • "singleTask "
  • "singleInstance "

这些模式的在以下四方面不同:

  • 哪个任务将持有响应意图(intent)的活动 。对"standard "和"singleTop "模式,是产生意图的任务(调用startActivity() 方法)——除非Intent 对象包含FLAG_ACTIVITY_NEW_TASK 标志。在那种情况下,像上一节亲和度和新任务(Affinities and new tasks)所描述的那样选择一个不同的任务。
    相反,"singleTask "和"singleInstance "模式,总是将活动标记为一个任务的根活动。他们定义一个任务,而从不启动到其他任务。
  • 活动是否可以实例化多次 。"standard "或"singleTop "活动可以实例化多次。这些实例可以属于多个任务,且一个给定任务可以包含同一个活动的多个实例。
    相反,"singleTask "和"singleInstance "活动仅可以被实例化一次。因为这些活动是一个任务的根,这个限制意味着设备上一个时间只有不多于一个任务的实例。
  • 是否允许实例所在任务有其他活动 。"singleInstance "活动所在任务只有它一个活动。如果他启动别的活动,那些活动将启动到不同的任务中,无论它的模式如何——就好像Intent 对象包含FLAG_ACTIVITY_NEW_TASK 标志。在所有其他方面,"singleInstance "模式等同于"singleTask "模式。
    其它三种模式允许多个活动属于一个任务。"singleTask "活动总是任务的根活动,但是它能启动其他活动到它的任务。"standard "或"singleTop "活动的实例可以出现的栈中的任何位置。
  • 响应一个意图时是否需要生成类的新实例 。对于默认的"standard "模式,创建新的实例去响应每一个新的意图。每个实例仅处理一个意图。对于"singleTop "模式,一个类已存在的实例可以重新用了处理新的意图,如果它位于目标任务的活动栈的栈顶。如果不是在栈顶,就不可以重用。相反,将创建一个新的实例并压入栈顶。
    例如,一个任务的活动栈由根活动A、B、C和D组成,顺序为A-B-C-D。当一个意图到达请求类型D时,如果D是默认的"standard "模式,将产生D类的新实例且栈变为A-B-C-D-D。然而,如果D的启动模式是"singleTop ",已存在的D实例将去处理新的意图(因为它在栈顶)且栈仍然是A-B-C-D。
    如果,另一方面,到达的意图是请求类型B时,一个B的新实例将启动而不管B的模式是"standard "还是"singleTop "(因为B不是在栈顶),因此栈的结构为A-B-C-D-B。
    如前所述,"singleTask "和"singleInstance "活动仅可以被实例化一次,因此他们的实例将处理所有的新意图。一个"singleInstance "活动总是在栈顶(因为仅有一个活动在任务中),因此它总是在可以处理意图的位置。然而,一个"singleTask "活动在栈中可能有或可能没有其他活动在它上面。如果有,即它不在处理意图的位置,意图会被丢弃(即使意图被丢弃了,它的到来使任务转到并保持在前台运行)

当一个已存在的活动被请求处理一个新的意图,Intent 对象将通过onNewIntent() 调用传到活动。(产生启动活动的意图对象可以由getIntent() 获取。)

注意到当一个活动的新实例被创建去处理新意图时,用户总是可以按返回键返回到之前的状态(之前的活动)。但是当一个已存在的活动实例去处理新意图是,用户不可以按返回键返回到意图到达之前的状态。

4、清除栈(Clearing the stack)

如果用户离开一个任务很长时间,系统将会清除根活动之外的活动。当用户再次返回到这个任务时,像用户离开时一样,仅显示初始的活动。这个想法是,一段时间后,用户可能已经放弃之前做的东西,及返回任务做新的事情。这是默认情况,有些活动属性可以用来控制和改变这个行为。

  • alwaysRetainTaskState 属性
    如果在任务的根活动中这个属性被设置为"true ",刚才描述的默认行为将不会发生。任务将保留所有的活动在它的栈中,甚至是离开很长一段时间。
  • clearTaskOnLaunch 属性
    如果在任务的根活动中这个属性被设置为"true ",只有用户离开就清除根活动之外的活动。换句话说,它与alwaysRetainTaskState 截然相反。用户总是返回到任务的初始状态,甚至是只离开一会。
  • finishOnTaskLaunch 属性
    这个属性类似于clearTaskOnLaunch ,但是它作用于单个活动,而不是整个任务。而且它能移除任何活动,包括根活动。当它被设置为"true ",任务本次会话的活动的部分还存在,如果用户离开并返回到任务时,它将不再存在。

有其他的方法强制从栈中移除活动。如果Intent 对象包含FLAG_ACTIVITY_CLEAR_TOP 标志,目标任务已经有一个指定类型的活动实例,栈中该实例上面的其它活动将被移除而使它置于栈顶响应意图。如果指定的活动的启动类型是"standard ",它自己也将被移除出栈,且一个新的实例将被启动去处理到来的意图。这是因为当模式是"standard "时,总是创建一个新的实例去处理新的意图。

FLAG_ACTIVITY_CLEAR_TOP 标志经常与FLAG_ACTIVITY_NEW_TASK 一起使用。当一起使用时,这些标志的方式是定位到另一个任务中的已存在的活动并把它放到可以处理意图的位置。

5、启动任务(Starting tasks)

通过给定活动一个意图过滤器"android.intent.action.MAIN "作为指定行为(action)和"android.intent.category.LAUNCHER "指定种类(category),活动就被设置为任务的入口点了。上篇Android开发之旅:应用程序基础及组件(续) 第四节Intent过滤器中我们举了这样一个例子,它将导致该活动的图标(icon)和标签(label)显示在应用程序启动器,给用户启动它或启动之后任意时候返回到它。

它的第二个功能非常重要:用户可以离开任务且之后可以返回到它。基于这个原因,两个启动模式"singleTask "和"singleInstance "标记活动总是初始化一个任务来响应意图,仅可以使用在有MAINLAUNCHER 过滤器的活动中。想象一下,如果没有这个过滤器将会发生什么:一个意图启动一个"singleTask "活动,开始一个新任务,用户在任务中做一些操作。然后用户按下HOME键,任务现在退到后台运行且被主屏幕遮蔽住。而且,由于活动不在应用程序启动器中显示,用户无法再返回。

类似的困难也出现在FLAG_ACTIVITY_NEW_TASK 标志。如果这个标志导致一个活动开始一个新的任务且用户按HOME键离开它,就必须要有某种方法是用户能够导航回来。一些实体(如通知管理器)总是在外部任务启动活动,从不作为他们自己的一部分,因此他们总是将带FLAG_ACTIVITY_NEW_TASK 标志的意图传到startActivity() 方法启动活动。如果你有活动能调用外部实体,可以使用此标志,注意用户有一个独立的方式返回到开始的任务。

如果您希望用户离开活动后就不能再回到这个活动,可以将<activity> 元素的finishOnTaskLaunch 属性设置为"true "。可以参见清除栈那节。

 

作者:吴秦
出处:http://www.cnblogs.com/skynet/
本文基于署名 2.5 中国大陆 许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦 (包含链接).

分享到:
评论

相关推荐

    Android开发之旅

    Android开发之旅:活动与任务 6 Android开发之旅:进程与线程 7 Android开发之旅:组件生命周期(一) 8 Android开发之旅:组件生命周期(二) 9 Android开发之旅:组件生命周期(三) 10 Android 开发之旅:又...

    android开发关键技术之旅

    在“Android开发关键技术之旅”这个资源中,您将踏上成为一名熟练Android开发者的旅程。这个学习资料包特别适合那些已经有Java编程基础...在学习过程中,不断实践和反思是关键,祝您在Android开发之路上取得丰硕成果!

    Android平台开发之旅 源代码

    总的来说,"Android平台开发之旅"的源代码提供了丰富的学习资源,涵盖了Android开发的各个方面,包括基本概念、核心组件、架构设计、服务集成、资源管理和测试策略。通过仔细研究和实践这些代码,你不仅可以深化对...

    Android平台开发之旅(第2版)光盘

    《Android平台开发之旅(第2版)光盘》是一本深度探索Android开发的书籍,针对Android 3/4系统的新特性进行了详细的解析。这本书旨在通过实际的开发案例,帮助读者理解并掌握Android平台开发的基本概念、实用技术...

    Android平台开发之旅 第2版

    《Android平台开发之旅 第2版》是一本专为Android开发者准备的详细指南,旨在帮助读者深入理解Android系统以及如何在该平台上构建应用程序。这本书由汪永松撰写,提供了丰富的实践经验和理论知识,覆盖了Android开发...

    Android平台开发之旅(第2版).pdf

    根据提供的文件信息,“Android平台开发之旅(第2版).pdf”这一资料似乎是一本关于Android应用开发的专业书籍。虽然给出的部分内容并未包含实际的知识点,但从书名和描述来看,我们可以推断出这本书可能覆盖的一些...

    Android开发之旅(2):android架构.rar

    在Android开发之旅(2):android架构的主题中,我们将深入探讨Android系统的架构,这是一个复杂的多层次设计,涵盖了操作系统、中间件层、应用程序框架以及各种应用程序。Android的架构是其强大功能和灵活性的基础,...

    Android开发之旅(2):android架构.pdf

    【Android开发之旅(2): Android架构】 Android架构是理解Android操作系统基础的重要环节,它由五个主要部分构成:Linux Kernel、Android Runtime、Libraries、Application Framework和Applications。在深入探讨每个...

    android开发之旅11[参照].pdf

    在Android开发之旅中,我们已经探索了许多核心概念和组件,为深入学习打下了坚实的基础。首先,我们了解了Android应用程序的基本目录结构,其中包括src、gen、Android x、assets、AndroidManifest.xml以及default....

    老罗的android之旅导读ppt

    通过【老罗的Android之旅导读PPT】,你将获得对Android系统全面而深入的理解,为你的Android开发之路打下坚实的基础。这份资料不仅适合初学者,也对有经验的开发者有很高的参考价值,因为它涵盖了从基础到高级的多个...

    Android游戏开发之旅.pdf

    在描述的"Android游戏开发之旅"中,作者详细介绍了如何为Button添加长按功能,特别是通过扩展ImageButton来实现。 首先,创建了一个名为RepeatingImageButton的自定义类,继承自ImageButton。这个类的目的是提供一...

    android开发之旅3.pdf

    在Android开发之旅中,深入理解Android系统的架构是至关重要的。本篇主要探讨Android系统架构的五个核心组成部分:Linux Kernel、Android Runtime、Libraries、Application Framework和Applications。 1. **Linux ...

    人气专家】老罗的Android之旅.

    《老罗的Android之旅》是一份关于Android操作系统深入探索的学习资料集合,包含了多个PPT文件,每个文件都可能涵盖不同的主题和知识点。这些文件可能是老罗(可能是一位知名的IT专家或教师)在教学或分享中使用的,...

    Android平台开发之旅(第2版)

    通过阅读《Android平台开发之旅(第2版)》,开发者不仅可以学习到Android开发的基本技能,还能了解最佳实践和行业趋势,从而为自己的Android开发之旅奠定坚实基础。无论你是对移动开发充满热情的初学者,还是希望深化...

    老罗Android之旅系列课件

    《老罗的Android之旅》是一套深受Android开发者欢迎的学习资源,由知名技术讲师老罗精心制作。这个压缩包集合了该课程的多个关键主题的PPT文件,旨在为那些希望深入理解Android系统的开发者提供一站式学习材料。以下...

Global site tag (gtag.js) - Google Analytics