Task和Back Stack

本文深入解析Android应用中Activity的启动模式(如standard、singleTop、singleTask、singleInstance)及其对Task的影响,解释了如何通过设置Activity的TaskAffinity属性来定制Task栈,并详细阐述了清理backstack机制及其相关属性(如alwaysRetainTaskState、clearTaskOnLaunch、finishOnTaskLaunch)的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念
Task 是多个 activity 的集合,用户进行操作时将与这些 activity 进行交互。 这些 activity 按照启动顺序排队存入一个栈(即“Back Stack”)。Task仅仅是一个集合,用来装activity,而Back Stack以一定的顺序的保存着activity,它里面的activity可能涉及到不同的task。这里举个例子:
浏览器的browser activity设置了SingleTask只运行在它自己的task中,如果Browser的task现在正在后台当中(task B),而我们的app(task A)的正要打开这个activity,这个task就会被直接移到前台接收我们的intent。返回键只会将界面返回到当前task的下一个activity,所以Task B回到前台后,返回键会先作用在Task B中,直到最后一个activity被弹出,才会回到我们的Task A栈顶的activity。

一个 Task 是一个整体单位。当 task 处于后台时,其中所有的 activity 都处于停止状态,但系统会保存 task 中每个 activity 的状态而且这个 task 的 back stack 仍然完整保留

Activity启动模式

  • “standard” (默认模式)

默认值。系统在启动 activity 的 task 中创建一个新的 activity 实例,并把 intent 传送路径指向它。该 activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中也可以存在多个实例。

  • “singleTop”

如果 activity 已经存在一个实例并位于当前 task 的栈顶,则系统会调用已有实例的onNewIntent()方法把 intent 传递给已有实例,而不是创建一个新的 activity 实例。activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中可以存在多个实例(但仅当 back stack 顶的 activity 实例不是该 activity 的)。
比如,假定 task 的 back stack 中包含了根 activity A 和 activities B、C、D(顺序是 A-B-C-D;D 在栈顶)。
这时过来一个启动 D 的 intent。如果 D 的启动模式是默认的”standard”,则会启动一个新的实例,栈内容变为 A-B-C-D-D。
但是,如果 D 的启动模式是”singleTop”,则已有的 D 实例会通过onNewIntent():接收这个 intent,因为该实例位于栈顶——栈中内容仍然维持 A-B-C-D 不变。当然,如果 intent 是要启动 B 的,则 B 的一个新实例还是会加入栈中,即使 B 的启动模式是”singleTop”也是如此。
注意: 一个 activity 的新实例创建完毕后,用户可以按回退键返回前一个 activity。 但是当 activity 已有实例正在处理刚到达的 intent 时,用户无法用回退键回到 onNewIntent() 中 intent 到来之前的 activity 状态。

  • “singleTask”

系统将创建一个新的 task,并把 activity 实例作为根放入其中。但是,如果 activity 已经在其它 task 中存在实例,则系统会通过调用其实例的onNewIntent() 方法把 intent 传给已有实例,而不是再创建一个新实例。 此 activity 同一时刻只能存在一个实例。举个列子:Activity A的启动模式为singleTask,当启动A时,系统首先会寻找A所需要的任务栈是否存在,如果存在,则为A创建一个A所需要的任务栈,如果任务栈存在,这时就要看此任务栈中是否有A的实例,如果此栈中存在A的实例,比如说栈由底向上的顺序是ABC,则系统会让BC出栈,将A调至栈顶,然后调用它的onNewIntent方法;如果栈中不存在A的实例,就创建A的实例并把它压入栈中。
上面提到了在singleTask启动模式中,某个Activity所需的任务栈,那这个所需的任务栈是如何定义的呢?Activity有一个参数TaskAffinity,翻译为中文任务相关性,这个参数标识了一个Activity所需的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名。

注意: 虽然 activity 启动了一个新的 task,但用户仍然可以用回退键返回前一个 activity。

  • “singleInstance”

除了系统不会把其它 activity 放入当前实例所在的 task 之外,其它均与”singleTask”相同。activity 总是它所在 task 的唯一成员;它所启动的任何 activity 都会放入其它 task 中。

在要启动 activity 时,你可以在传给 startActivity() 的 intent 中包含相应标志,以便修改 activity 与 task 的默认关系。这个标志可以修改的默认模式包括:

FLAG_ACTIVITY_NEW_TASK
这个过程与前一节所述的”singleTask”launchMode模式值相同。
FLAG_ACTIVITY_SINGLE_TOP
这个过程与前一节所述的 “singleTop”launchMode模式值相同。
FLAG_ACTIVITY_CLEAR_TOP
如果要启动的 activity 已经在当前 task 中运行,则不再启动一个新的实例,且所有在其上面的 activity 将被销毁,然后通过onNewIntent()传入 intent 并恢复 activity(不在栈顶)的运行。
此种模式在launchMode中没有对应的属性值。

FLAG_ACTIVITY_CLEAR_TOP 常与 FLAG_ACTIVITY_NEW_TASK 一起使用。这表示先定位其它 task 中已存在的 activity,再把它放入可以响应 intent 的位置。

清理back stack

如果用户长时间离开某个 task,系统将会仅保留一个根 activity,而把其它 activity 都清除掉。 当用户返回 task 时,只有根 activity 会被恢复。 系统之所以这么处理,是因为经过了很长时间后,用户是要放弃之前进行的工作,返回 task 是为了开始新的工作。

你可以利用 activity 的某些属性来改变这种方式:

  • alwaysRetainTaskState

如果 task 中根 activity 的此属性设为 “true” ,则默认的清理方式不会进行。即使过了很长时间,task 中所有的 activity 也都会保留在栈中。

  • clearTaskOnLaunch

如果 task 中根 activity 的此属性设为 “true”,则只要用户离开并再次返回该 task,栈就会被清理至根 activity。也就是说,正好与alwaysRetainTaskState相反。用户每次返回 task 时看到的都是初始状态,即使只是离开一会儿。

  • finishOnTaskLaunch

此属性类似于clearTaskOnLaunch,只是它只对一个 activity 有效,不是整个 task。这能让任何一个 activity 消失,包括 根 activity。如果 activity 的此属性设为 “true”,则只会保留 task 中当前 session 所涉及的内容。如果用户离开后再返回 task,它就不存在了。

资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 华为移动服务(Huawei Mobile Services,简称 HMS)是一个全面开放的移动服务生态系统,为企业开发者提供了丰富的工具 API,助力他们构建、运营推广应用。其中,HMS Scankit 是华为推出的一款扫描服务 SDK,支持快速集成到安卓应用中,能够提供高效且稳定的二维码条形码扫描功能,适用于商品扫码、支付验证、信息获取等多种场景。 集成 HMS Scankit SDK 主要包括以下步骤:首先,在项目的 build.gradle 文件中添加 HMS Core 库 Scankit 依赖;其次,在 AndroidManifest.xml 文件中添加相机访问互联网访问权限;然后,在应用程序的 onCreate 方法中调用 HmsClient 进行初始化;接着,可以选择自定义扫描界面或使用 Scankit 提供的默认扫描界面;最后,实现 ScanCallback 接口以处理扫描成功失败的回调。 HMS Scankit 内部集成了开源的 Zxing(Zebra Crossing)库,这是一个功能强大的条码二维码处理库,提供了解码、生成、解析等多种功能,既可以单独使用,也可以与其他扫描框架结合使用。在 HMS Scankit 中,Zxing 经过优化,以更好地适应华为设备,从而提升扫描性能。 通常,ScanKitDemoGuide 包含了集成 HMS Scankit 的示例代码,涵盖扫描界面的布局、扫描操作的启动停止以及扫描结果的处理等内容。开发者可以参考这些代码,快速掌握在自己的应用中实现扫码功能的方法。例如,启动扫描的方法如下: 处理扫描结果的回调如下: HMS Scankit 支持所有安卓手机,但在华为设备上能够提供最佳性能体验,因为它针对华为硬件进行了
<think>嗯,用户想了解鸿蒙系统中的“stack”相关概念或编程实现。首先,我需要确认“stack”在HarmonyOS中的具体含义。可能涉及数据结构中的栈,或者是系统层面的堆栈管理,比如内存堆栈、任务堆栈等。 首先,检查已有的引用内容。引用[1]提到了函数式编程,避免副作用,这可能与栈的操作有关,但不确定。引用[2]讨论事件驱动架构,可能涉及消息队列,但用户的问题更偏向系统底层。引用[3]中的BankAccount类示例,可能与堆栈无关。因此,可能需要依赖其他知识。 鸿蒙系统(HarmonyOS)是分布式操作系统,支持多种设备。在编程中,栈可能涉及内存管理或任务调度。例如,每个任务可能有自己的堆栈空间,用于保存函数调用局部变量。此外,应用开发中的页面堆栈管理,比如导航栈,用于管理页面跳转。 需要确认HarmonyOS的文档或开发者资源。例如,在应用框架中,Page Ability的导航使用堆栈管理,类似Android的Activity栈。另外,底层任务调度中的堆栈分配也很重要,确保任务隔离高效执行。 可能还需要考虑轻量级内核LiteOS-M/A中的栈实现,比如任务创建时的栈大小配置,防止溢出。此外,HarmonyOS的Ark UI框架中的组件堆栈布局,如Stack容器组件,用于界面设计。 总结,用户可能需要了解应用层面的导航栈、系统任务堆栈或UI布局中的栈容器。需要分点说明,确保涵盖不同层面的实现,并提供代码示例相关问题供进一步学习。</think>### HarmonyOS中与Stack相关的实现及概念 在HarmonyOS中,“Stack”可能涉及以下三个层面的实现或概念: --- #### 1. **应用导航栈(Page Stack)** 在应用开发中,HarmonyOS通过`Page Ability`实现页面导航栈管理。每个Ability的页面跳转会形成一个类似堆栈的结构,遵循**先进后出**原则: - **入栈操作**:通过`present()`方法跳转新页面。 - **出栈操作**:通过`terminateSelf()`返回上一页面。 ```typescript // 示例:页面跳转(ArkTS) import router from '@ohos.router'; // 跳转至新页面(入栈) router.pushUrl({ url: 'pages/NewPage' }); // 返回上一页面(出栈) router.back(); ``` 这种设计确保了页面状态的有效管理[^1]。 --- #### 2. **任务调度栈(Task Stack)** 在系统内核层,HarmonyOS LiteOS-M/A内核通过任务堆栈管理多任务执行: - 每个任务在创建时分配独立的**栈空间**,用于保存函数调用链局部变量。 - 栈大小需合理配置以避免溢出: ```c // LiteOS任务创建示例(C语言) #define TASK_STACK_SIZE 0x1000 // 4KB栈空间 LOS_TaskCreate(&taskId, taskEntry, priority, &stackMem, TASK_STACK_SIZE); ``` 任务切换时,内核自动保存/恢复栈内上下文,确保多任务隔离运行[^2]。 --- #### 3. **UI布局容器(Stack Component)** 在ArkUI框架中,`Stack`容器用于叠加组件,适用于浮动按钮、弹窗等场景: ```typescript // Stack布局示例(ArkTS) @Entry @Component struct StackExample { build() { Stack({ alignContent: Alignment.BottomEnd }) { Text("背景层") .width(200).height(200).backgroundColor(Color.Gray) Button("浮动按钮") .width(50).height(50) } } } ``` `Stack`通过层级叠加实现灵活布局[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值