<!--正文 begin-->
引言
关于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"标记活动总是初始化一个任务来响应意图,仅可以使用在有MAIN和LAUNCHER过滤器的活动中。想象一下,如果没有这个过滤器将会发生什么:一个意图启动一个"singleTask"活动,开始一个新任务,用户在任务中做一些操作。然后用户按下HOME键,任务现在退到后台运行且被主屏幕遮蔽住。而且,由于活动不在应用程序启动器中显示,用户无法再返回。
类似的困难也出现在FLAG_ACTIVITY_NEW_TASK
标志。如果这个标志导致一个活动开始一个新的任务且用户按HOME键离开它,就必须要有某种方法是用户能够导航回来。一些实体(如通知管理器)总是在外部任务启动活动,从不作为他们自己的一部分,因此他们总是将带FLAG_ACTIVITY_NEW_TASK
标志的意图传到startActivity()方法启动活动。如果你有活动能调用外部实体,可以使用此标志,注意用户有一个独立的方式返回到开始的任务。
如果您希望用户离开活动后就不能再回到这个活动,可以将<activity>元素的finishOnTaskLaunch
属性设置为"true"。可以参见清除栈那节。
分享到:
相关推荐
### Android学习资源与知识点概述 在当今移动互联网时代,Android操作系统作为全球最广泛使用的移动设备平台之一,其重要性不言而喻。对于开发者而言,掌握Android开发技能不仅能够提升个人职业竞争力,还能够为...
【第一部分】历史文章: Android学习笔记(一)——创建第一个Android项目 ...Android学习笔记(六)——自定义ListView布局+AsyncTask异步任务 Android学习笔记(七)——数据存储(共享参数Share
`TimeTask`框架巧妙地将`AlarmManager`与任务队列相结合,为开发者提供了一种易于使用且高效的解决方案。 框架的主要特点包括: 1. **任务封装**:`TimeTask`对`AlarmManager`进行了封装,隐藏了复杂的系统API使用...
这里我们关注的是"android学习小例子",它涵盖了Android应用开发中的关键元素:Activity、Service、Fragment以及Dialog。这些组件是构建Android应用程序的基础,理解并熟练运用它们对于成为一名合格的Android开发者...
在Android系统中,RecentsActivity是用户界面的一个关键部分,它负责展示最近使用的应用程序列表,通常被称为“最近任务”或“多任务切换器”。在Android 7(Nougat)版本中,这一功能得到了显著的改进,提升了用户...
一、任务与任务栈 在Android中,一个任务(Task)是一个应用程序执行的上下文,它可以包含多个活动(Activity)。任务栈(Task Stack)则是一个按照后进先出(LIFO)原则存储任务的结构,就像一个堆栈一样,新的...
这个小项目不仅展示了Android应用开发的基本技术,还涵盖了任务管理系统的设计与实现,是Android毕业设计或个人技能提升的良好实践案例。 1. **用户界面与交互设计** - Android Studio作为集成开发环境,用于创建...
在Android应用开发中,意图(Intent)是连接各个组件的核心机制,它用于启动新的活动(Activity)、服务(Service)或广播接收...通过上述知识点的学习,开发者可以更好地掌握Android活动间的通信机制,提升应用的用户体验。
1. **任务与任务栈** 在Android中,任务(Task)是由一组有前后关系的Activity组成,它们共享同样的上下文环境。当用户在不同的应用之间切换时,Android将这些Activity组织成一个栈(Task Stack),遵循“后进先出...
基于Android平台的在线学习社区的设计与实现,基于Android平台的在线学习社区设计采用了Java语言,基于web网站,数据库采用MySQL。系统主要分为用户和管理员三大功能模块,可以实现用户:个人中心、圈子、实践活动、...
通知服务也是在线学习平台不可或缺的一部分,开发者可能利用了Firebase Cloud Messaging(FCM)来实现消息推送,及时提醒用户新的课程或活动。同时,权限管理系统也是Android应用的重要部分,开发者需要适配Android...
在Android系统中,实现一个能够长期在后台运行的定时任务是一项关键的技术挑战,因为Android系统为了优化电池寿命和用户体验,可能会在应用不活跃时限制其后台活动。标题"Alarm.7z,Android定时任务"表明这是一个与...
1. **Android 进程与任务** - **进程(Processes)**:在Android中,每个应用都运行在自己的进程中。当应用启动时,Android会为它分配一个进程。进程是操作系统分配资源的基本单位。 - **任务(Tasks)**:任务是...
根据提供的文件信息,“Android任务驱动式教程.pdf”似乎是一份旨在帮助初学者通过完成特定任务来学习Android开发的教程。接下来我们将围绕这份教程可能涵盖的关键知识点进行深入探讨。 ### Android开发基础 - **...
在Android开发中,多任务下载是一项常见的需求,特别是在移动设备上,用户可能希望同时下载多个文件,如应用程序、音乐或视频。本示例"android多任务下载并显示Demo"聚焦于如何实现这样的功能,并通过一个按钮实时...
在本压缩包“AndroidStudio移动应用开发任务教程(微课版)_PPT课件和教案.zip”中,包含了一份详尽的Android Studio移动应用开发的教学资料,旨在帮助初学者和有一定基础的学习者掌握Android应用的开发技能。...
在Android操作系统中,任务栏(Task Bar)是用户界面的核心组成部分,它允许用户在不同的应用程序之间切换和管理活动。任务栏管理器(Task Manager)则是负责处理这些任务切换和管理的系统服务。本文将深入探讨...
通过分析这个DEMO,开发者可以学习到如何将上述技术实际应用到Android项目中,构建出自己的多任务断点下载系统。 总的来说,Android多任务断点下载是一项实用且复杂的功能,它涉及到网络编程、文件操作、线程控制等...
- **`android:allowTaskReparenting`**:指定当用户启动一个新任务时,该活动是否可以从其当前任务移动到新任务中。 - **`android:alwaysRetainTaskState`**:如果设置为 `true`,则当此Activity所在的Task被销毁时...