任务与活动栈

引用:http://blog.youkuaiyun.com/ba_jie/article/details/6581822

一个应用程序有很多Activity。Activity之间相互调用。通过传递Intent,还可以调用别的应用程序的Activity。
比如,你的应用程序要发送邮件,只需定义一个有SEND动作的Intent,Android就会在整个系统里查找合适的Activity,然后调用,然后发送。发送邮件的Activity就好像是你的应用程序的一部分一样。
Android把这些Activity都放入一个Task中,以保持它们之间的无缝过渡。所以,所谓的Task就是活动的集合。以栈的形式来管理,起个专有名词叫做Back Stack。

(后台栈、活动栈,这两者是一回事儿。)

HOME屏幕是Task启动的地方。
用户点击了Launcher上的应用程序的图标后,一个应用程序的Task就来到前台。如果还不存在,则先建立一个Task,然后把应用程序的“Main活动”打开,置入栈顶。
若当前Activity启动了第二个Activity,则自身变为停止状态,然后被压到栈的下一级。新启动的Activity置入栈顶。
用户若点击了BACK键,则刚建立的Activity被销毁,然后从栈中弹出。下面的Activity又回到栈顶,恢复成活动状态。
这个栈只有压栈弹栈两种操作,栈中的活动绝对不会因为某种原因去重新排列。
栈中所有东西被弹干净了,Task就消失了。用户会返回到HOME屏幕或前一个Task。
Task在运行时,若用户按了HOME键,或启动了新Task,则老Task被移到后台,所有Activity都成为停止状态。
若用户重新回到HOME屏幕,又选了原来的应用程序,则后台的Task重回到前台,栈顶的Activity恢复为活动状态。

这就是Android的多任务系统。
但后台的Task变多时,系统会在内存吃紧时杀掉其中一些Activity。需要Activity在合适的时机保存所有数据。

因为活动栈从不会重排,若某个Activity比较受欢迎,很多Activity都启动它,就会导致在栈中有多个它的实例。(而不是把栈底的实例移到栈顶)
用户可能会不喜欢这样的操作感受(多按几次BACK键,却能回到同一个Activity的UI界面,会迷惑),可以配置该Activity只能在栈中有一个实例。

系统在内存吃紧时,强行杀掉某些Task的某些Activity,但是却在栈中仍然不弹出。
当用户重新回到该Task的已死的Activity,系统会重建该活动。所以,在onSaveInstanceState()回调方法中保存用户数据是一个好主意。

● 管理Task

你可能希望某个Activity被启动时不是被放到栈顶,而是重新建立一个Task。这样,它在Task栈中总是唯一的。
你也可能希望某个Activity启动时,先从栈底看是否已有被压下的实例,若有则恢复之。
你也可能希望在用户离开某Task时,把活动栈清干净,只剩下一个Root活动(即最先启动的Activity)。

这需要两方面的工作:AndroidManifest.xml的<activity>属性,和startActivity()所用的Intent的标志参数。有了这些东西,Activity就知道自己如何和Task联系。

<activity>主要有下面这些属性可用:
- taskAffinity
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch

Intent标志有:
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_SINGLE_TOP

● 亲密度 - affinity
一个Activity启动时,放入哪个Task栈中,是由亲密度来决定的。
默认情况下,一个应用程序的所有Activity拥有相同的亲密度,所以它们会聚集在一个栈里。这个亲密度就是应用程序的包名(Package Name)。
你可以改变一个Activity的亲密度,让不同的应用程序的两个Activity有相同的亲密度,或者同一个应用程序中的Activity有不同的亲密度。
在<activity>元素里定义taskAffinity属性即可。
该属性起作用的条件:
- Intent带有FLAG_ACTIVITY_NEW_TASK标志。系统看到此标志,就会在别的Task里找地方存放新的Activity。此时,就要根据亲密度来寻找。找不到就新建一个Task。
- Activity有一个属性allowTaskReparenting="true"的时候。
举例:一个旅游软件,某个Activity的功能是报告天气的,亲密度和应用中其它的Activity一样,都是默认值,不过,其allowTaskReparenting属性是true。
此时,你的应用程序启动了这个天气报告Activity,那么,它就来到了你的Task栈中。
当那个旅游软件启动了并跑到前台时,该天气报告Activity又跑回去了,回到旅游软件的Task栈里。

● 后台栈的清除
当一个Task在后台呆时间太长时,系统会把栈内的Activity清干净,只剩下Root活动。
如果用户此时回到该Task,那他只能回到Root活动。

有几个属性可以更改这种行为。
- alwaysRetainTaskState 如果设为true,那么Task里所有的活动都留下。
- clearTaskOnLaunch 如果Task的Root活动此属性为true,则每次用户离开该Task,栈都会被清一遍。和上面正相反。
- finishOnTaskLaunch 和上面类似,但只作用于一个Activity,而非整个Task。用户一离开,该Activity立刻销毁。

● Task的入口 - Root活动

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>
若某Activity设置了上面那样的IntentFilter,其图标和名字将出现在Launcher屏幕上,作为整个应用程序的入口。
用户必须能够退出且能从Launcher回到该Activity,所以singleTask和singleIntance这两个属性,只能用于带ACTION_MAIN和CATEGORY_LAUNCHER配置的Activity。
假设这两个配置缺少了,会出现什么问题呢?
打比方,用户使用Intent启动了一个singleTask的新任务,然后按HOME键把它压入后台。该Activity如何被用户重新选择回来?只有带MAIN和LAUNCHER才行


<think>好的,我现在需要向用户介绍什么是任务。首先,我得回忆一下自己对这个概念的理解。任务在Android系统中是一个重要的概念,用于管理应用的活动。用户可能是在学习Android开发或者对系统原理感兴趣,所以需要从基础开始解释。 任务,也叫返回(Back Stack),用来管理用户的操作历史。每个应用启动一个活动,系统会将其压入顶,用户按返回键时,活动弹出,之前的活动显示出来。这应该是任务的基本工作原理。接下来,我需要用简单的中文来解释,避免使用专业术语过多,同时确保结构清晰。 用户的问题可能涉及任务的作用、结构以及应用场景。比如,当用户打开多个应用或同一应用的不同活动时,任务如何管理这些活动。需要举例说明,比如用户从主屏幕启动应用A,打开活动A1,然后跳转到A2,这时中有A1和A2。按返回键,A2出,回到A1。如果从A1启动应用B的活动B1,此时任务可能分为两个,或者根据启动模式不同而变化,这里可能需要提到不同的启动模式,如standard、singleTop等,但用户的问题可能不需要太深入,所以点到为止。 另外,需要提到任务对用户体验的影响,比如多任务处理时,系统如何维护不同的,用户切换应用时的行为。可能还要提到Android的多窗口模式对任务的影响,但不确定是否需要详细说明,根据用户问题,可能暂时不需要。 需要检查是否有遗漏的关键点,比如任务的生命周期管理,系统如何恢复中的活动等。例如,当系统资源不足时,可能会销毁中的某些活动,但在用户返回时重新创建它们。这点对开发者来说很重要,但用户可能作为普通用户不需要了解,但如果是开发者提问,可能需要涉及。不过用户的问题没有明确身份,所以可能需要兼顾。 另外,任务和进程的区别,任务活动的集合,而进程是应用的运行实例,两者不同但相关。可能用户会混淆这两个概念,所以需要简要说明。 结构方面,先定义任务,然后解释工作原理,接着举例说明,再提到相关的启动模式,最后可能涉及开发中的注意事项。确保用中文,行内公式如果有的话用$...$,独立公式用$$...$$,但这个问题可能不需要数学公式,不过需要确认用户的问题是否需要。用户的问题是关于任务的,可能不需要数学表达式,但系统指令中提到行内数学表达式的格式,所以如果有用到变量或术语,可能需要用格式,但这里可能用不到,所以暂时忽略。 需要确保语言口语化,避免生硬。比如使用“举个例子”,“需要注意的是”等过渡词。同时按照系统指令,结构要清晰,分点或分段落,帮助用户逐步理解。 可能还需要提到任务在Android版本中的变化,比如在早期版本和现在的版本中任务的管理是否有差异,但可能超出用户的问题范围,所以暂时不提。 总结下来,回答的结构应该是: 1. 定义任务 2. 作用和工作原理 3. 示例说明 4. 启动模式的影响 5. 进程的区别 6. 开发注意事项或用户体验相关 需要检查是否有错误,比如任务是否真的是后进先出的结构,是的,活动确实是压和出的操作。另外,默认启动模式是standard,每次启动新活动都会创建新实例,而singleTop如果已在顶则复用,这些需要准确描述。 可能用户会想知道任务如何影响应用的行为,比如为什么按返回键会回到上一个页面,这就是任务的作用。需要确保例子简单明了。 最后,确保回答符合系统指令中的格式要求,没有使用任何markdown,纯文本,分段落,结构清晰。使用中文,避免技术术语过多,必要时解释术语。</think>任务(Task Stack),也称为返回(Back Stack),是Android系统中用于管理应用内多个活动(Activity)的机制。它遵循“后进先出”(LIFO)原则,确保用户通过导航键操作时能按逻辑顺序回退到之前的界面。以下从原理、作用和使用场景逐步说明: --- ### 1. **基本工作原理** - **结构**:任务是一个存储活动的堆。当用户启动一个新活动(例如从主屏幕打开应用或从当前活动跳转),系统会将该活动**压入顶**;当用户按返回键时,活动**弹出**,前一个活动重新显示。 - **多任务管理**:每个应用可能对应一个或多个任务。例如,用户从应用A跳转到应用B的活动时,系统可能为应用B新建一个任务(取决于活动启动模式)。 --- ### 2. **核心作用** - **导航回退**:保证用户通过返回键能按顺序回退到之前的界面。 - **隔离任务**:不同应用或同一应用的不同功能流程(如聊天和邮件)可拥有独立的任务,避免界面混乱。 - **生命周期管理**:系统根据活动的状态(如是否可见)自动调用其生命周期方法(如`onPause()`、`onResume()`)。 --- ### 3. **示例说明** 假设用户操作如下: 1. 从桌面启动**应用A**,打开活动`A1` → 内容:`[A1]`。 2. 从`A1`跳转到`A2` → 内容:`[A1, A2]`。 3. 从`A2`跳转到**应用B**的活动`B1` → 系统可能新建一个:`[B1]`。 4. 按返回键 → 关闭`B1`,回到`A2` → 原恢复:`[A1, A2]`。 --- ### 4. **启动模式的影响** 活动的启动模式(在`AndroidManifest.xml`中定义)会改变任务行为: - **standard**(默认):每次启动新活动都创建新实例,压入当前。 - **singleTop**:若目标活动已在顶,则复用实例;否则新建。 - **singleTask**:为目标活动创建独立任务,且内只保留一个该活动实例。 - **singleInstance**:类似`singleTask`,但任务中仅能存在该活动。 --- ### 5. **任务进程的区别** - **任务**:是活动的逻辑集合,用户操作流程相关。 - **进程**:是应用的实际运行实例,负责执行代码和分配内存。 两者可能一对一,也可能一对多(例如同一进程包含多个任务)。 --- ### 6. **开发者注意事项** - **避免臃肿**:及时关闭无用活动,防止内存泄漏。 - **合理使用启动模式**:例如,登录页常用`singleTask`避免重复登录。 - **处理配置变更**:屏幕旋转等操作可能导致活动重建,需通过`onSaveInstanceState()`保存状态。 --- ### 总结 任务通过堆机制管理活动跳转逻辑,是Android多任务和用户体验的基础。理解其原理和启动模式,能帮助开发者优化应用导航设计,提升流畅性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值