Activity之理解Tasks和Back Stack
Task是一组Activity的集合,用户与之交互用于完成一个特定的任务。所有的Activity被安排在一个stack中称之为back stack, Activity按照打开的顺序存放于其中。例如,一个邮件APP可以有一个用于显示接收的新邮件列表的Activity。当用户选择一封邮件,那一个新的Activity会打开显示其内容。这个新的Activity就会被添加到back stack。 如果用户按下Back按钮,那么这个新打开的Activity会被finish并从stack中弹出消失。
当App运行在Android7(API Level 24)或更高版本的多窗口的环境中,系统会为每一个窗口单独管理task;每一个窗口可以拥有多个task。 设备的Home屏幕是用于启动绝大多数task的地方。当用户触点Launcher桌面App图标时,App的task会进入前台运行。如果App对应的task并不存在(最近用户并未打开过App),就会创建一个新的task,把打开应用的入口Activity放在stack中作为根Activity。 如果当前Activity启动另外一个Activity,那么新打开的Activity会被压到stack的顶端并得到焦点。而前一个Activity会保留在stack中,并处于stopped状态。一个stop的Activity,系统会保留它与用户交互的状态。当用户触点Back按钮。当前的Activity会从栈顶弹出(Activity被销毁)而前一个Activity会重新进入可见状态(UI状态被恢复)。在stack中的Activity并不会被重新安排,仅只做弹出和压入的动作。back stack保持着“后进,先出”的数据结构。如下图所示
图1
图1表示新的Activity是如何添加到back stack中的,当用户触点Back按钮时,当前Activity被销毁并使前一个Activity可见。
如果用户继续按Back按钮,那么stack中的Activity会顺次弹出并暴露出前一个Activity,直到用户返到Home屏幕(或者直到启动这个task的Activity),当所有的activity全部都从stack中移除后,stack也不复存在了。
在用户启动一个新task或者按home按钮返回到home屏幕时,task是一个可以整体移至后台的单位。当移入后台时,task中的所有activity都会进入stop状态,失去了焦点,显示如同图2
图2 (有两个task, taskB接受到用户的操作移到前台,同时taskA 移于后台等待重新恢复到前台)
task可以恢复到前台,用户得以可以继续操作,相反,例如,当前task A在stack中保存有三个activity,有两个activity在当前activity的下面。用户按下Home按钮,然后从Launcher桌面上启动一个新的app, 当home屏幕出现时,task A进入后台,当新的app启动时,系统为它启动一个新的task B用来存放stack, 在用户和app交互后,用户再次返回home屏幕,并再次选择原来启动task A的app。 现在,task A再次回到前台,在它的stack中依然保持着三个activity,stack顶部的activity变为可见。同理,用户也可以通过home键返回home屏幕,并再选择进和task B的app图标(或者从最近使用的APP)。以上是一个Android多task的例子。
注意:多task可以被保存后台,然而,如果用户在后台运行太多的task时,系统可以销毁后台的activity用于恢复内存,这会引发activity的状态丢失。
在stack中的activity重来不会被主动重新排序,但如果用户主动请求一个activity多次时,一个新activity实例会被创建并压入栈中(而不是把前面已创建的实例移于栈顶)。如图3
图3
如果用户用back按钮返回时,每一个activity实例都会得以展示(带有自己的ui状态)。然而,你可以修改这个行为,如果你不希望activity被实例化多次。如果做呢?见后面讨论的管理task。
总结一下activity和task的默认行为:
- 当activity A启动activity B, Activity A被stop, 但系统会保存它的ui状态(如滚动条的位置,表单中输入的文字)。如果用户在Activity B按下Back按钮, Activity A会重新显示并恢复它的状态。
- 当用户离开task通过按下home键,当前的activity会被stop,它对应的task会进入后台,系统会保留task中的每一个activity的状态,如果用户稍后选择app icon,可以重新切回task,task的栈顶activity变为可见
- 如果用户按下back按钮,当前activity会被弹出栈顶划被销毁,栈中的前一个activity变为可见。当activity被销毁时,系统不再保留它的状态。
- activity可以被创建多次,甚至可以位于不同的task
管理Task
如上所述,Android管理task和stack的方式就是把所有的activity一连串的放在同一个task中并按“后进,先出”的原则管理。你可以打破这一惯例,也许你希望一个activity启动时时放在一个新的task中(而不是当前task),或者,你希望启动一个已经存在的activity,而不是在栈顶再创建一个新的activity实例。或者你希望在用户离开task时只保留栈底的根activity,并清除掉其它的activity
你可以做到或做到更多,通过在manifest的<activity>声明中带上属性或者通过在startActivity()时使用Intent带上标记。
相关的属性如下:
- taskAffinity
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
相关的标记如下:
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ATIVITY_SINGLE_TOP
下面的章节你会看到如何用属性和标记定义activity和task的关联,以及activity在stack中的行为。
定义Launch mode
Launch mode允许你定义activity实例与当前task如何关联,你可以定义不同的启动方式,通过下面介绍的两种方式:
- 用manifest
- 用Intent flag
有时可能会出现这种情况,例如Activity A 启动Activity B,Activity B可以在manifest中定义它如何与当前task关联,而Activity A也可以通过Intent来请求Activity B如何与当前task关联。这时,后者优先。
注意:有一些Launch mode在manifest中有效,而在flag中无效,反之亦然。
使用manifest配置
通过launchMode属性,它指定activity应该在哪一个task中启动,有四种不同的launch mode属性值:
-
standard(默认值) 系统在当前task中创建一个activity实例。activity可以被实例化多次,每一个实例可以属于不同的task,一个task中也可以有多个实例。
-
singleTop 如果一个activity实例已经位于当前task顶端,系统会发送给它intent并调用onNewIntent(), 而不是创建一个新的实例。Activity可以实例化多次,每一个实例可以属于不同的task,每一上task可以拥有多个实例(仅出现在stack顶端不存在activity的实例时)
例如,task的栈由根activity A,B,C, D在顶部,一个itent到达Activity D, 如果D是standard属性,一个新的实例会创建,stack成为A-B-C-D-D,然而,如果D是singleTop属性,那么D会收到intent并执行onNewIntent(),这时栈保持A-B-C-D。然而,如果itnent是发给B的,B如果是singleTop,那么B的实例会加入栈。
注意:当一个新的activity实例被创建,用户可以按back键返回前一个activity. 但是当存在的activity处理了新的intent执和onNewIntent(),那用户不能通过back返回到以前的状态.
- singleTask 系统创建一个新的task并实例activity放在task的栈底。然而,如果activity实例已存在一个task中,系统会发送intent并调用onNewIntent(),而不是创建一个新的实例。在任一时刻,只有一个activity的实例。
注意:虽然activity在一个新的task中启动,back操作仍可以返回前一个activity.
- singleInstance 如同singleTask,除了系统不会将其它activity放入保存当前的task中,这个activity永远单独存在于自己的task中;这个activity启动任意其他activity都会在其它的task打开.
举一个例子,Android浏览器app声明的web activity应该总是在它自己的task中打开--通过指定singleTask属性。这意味着,如果你的APP打开Android Browser,web activity不会出现在你的app页面对应的task,不论web activity是否已经存在。
不管activity是否启动新task还是和启动它的Activity在同一个task,back键总是将用户带到前一个activity.然而,如果你启动activity用singleTask,并且如果activity已经存在于一个后台task,那么整个task会移置前台。从这一点上讲,stack现包括了从task转移所有的activity。图4说明这一场景。
图4说明singleTask的activity如何被加入stack,如果activity已经是后台task的自有stack中,那么整个stack都被移到前台,在当前task的头部。
使用Intent标记
有如下标记可用:
-
FLAG_ACTIVITY_NEW_TASK 启动一个activity在一个新的task. 如果task已经存在并运行着一个你想启动的Activity,那么这个task被置于前台,并恢复activity的状态,调用onNewIntent() 这个行为与上面讨论的singTask Launch model相同。
-
FLAG_ACTIIVTY_SIGNLE_TOP 如果activity已经启动并且位于stack顶部,那么会被调用onNewIntent(),而不是创建一个新的实例。 这个行为同singleTop Launch model
-
FLAG_ACTIVITY_CLEAR_TOP 如果activity已经在当前task中运行,那么就不会新建实例,在其上的所有activity都会被销毁,这个activity会移到stack顶部并调用onNewIntent 这个值在launchMode中无对应配置
FLAG_ACTIVTY_CLEAR_TOP通常与FLAG_ACTIVITY_NEW_TASK连用,用于定位一个在其他task中已存在的activity,并移于task头部。
注意:如果launchMode设置为standard, 它也会被从stack中移除,而是重新创建一个新的实例,那是因为在standard模式下一个新的Intent就会导致创建一个新的activity实例。
处理affinity
affinity指task应该归属于哪个task. 默认情况下,同一个app的所有activity都有相同的affinity。所以默认情况下,同一个app的所有activity都属于同一个task,然而,你可以修改这一行为。不同app的activity可以共享affinity,所以同一app的activity也可以指定不同的affinity.
你可以修改<activity>的taskAffinity属性。 的taskAffinity属性是一个字符串值,它必须区分与<manifest>中定义的包名,因为系统使用这个名字做为默认affinity的值
affinity在两个状态下使用
-
当启动activity的Intent包括FLAG_ACTIVITY_NEW_TASK标记。默认情况下,一个activity调用startActivity()会导致,一个新的activity实例创建并放在同一个task的stack中,然而如果intent带有FLAG_ACTIVITY_NEW_TAS标记, 系统会寻找一个新的task存放新的Activity,通常会新建一个task,然而也可以不必创建,只要已经存在一个task且task的affinity与新activity的affinity相同,那么新的activity就会被放在task中,而不用新建。 如果activity放在新建的task中,那么用户点击home按钮离开activity时,就必须有留一条路让用户可以重新导航回来。例如,通知管理器总是启动activity在一个新的task中,因为它发出的intent总是带有FLAG_ACTIVITY_NEW_TASK, 如果你的activity可以从外部调用可以使用这种方式,如通过launch icon重新返回。
-
当activity的allowTaskReparenting属性设为true 在这种情况下,activity可以根据affinity从一个后台的task移到一个前台的task
举例,假设一个旅行内容的APP,它有一个根据选择的城市显示天气的activity, 这个Activity与应用里其他activity具有相同的affinity,并且它的allowTaskReparenting属性设为true。当你的APP调用天气的activity时,它会进入你activity对应的task, 然而,当旅行app置入前台时,它又会重新回到原来的task中。
清除stack
如果用户离开task较长时间,系统会清除掉task中所有的actvity,除了根activity,当用户再次返回task,只有根activity可以恢复状态,因为系统认为超出一定的时间,用户很可能已经放弃他们以前浏览的页面,返回时会新建页面。
有一些activity属性可以让你修改这一行为。
-
alwaysRetainTaskState 如果一个task的根activity的属性设为true, 那么默认的行为就不会发生。task会保留所有的activity在Stack中,即使用户离开很长时间。
-
clearTaskOnLaunch 如果一个task的根activity的属性设为true, 那么Stack中activity会被清除,但会保留根activity,换句话说,他是alwaysRetainTaskState相反的特性,用户返咽task时总是会发生又重新回到初始状态,即使用户只是离开了一小会儿。
-
finishOnTaskLaunch 这个属性比较象clearTaskOnLaunch,但是它只操作在一个activity上,而不是作用于整个task, 它可能让任何一个activity离开,包括根activity。当他设置为true时,task中只保留部分activity,当前activity不存在了。
启动task
你可以设置一个activity做为task的入口点,以"android.intent.action.MAIN" action和 "android.intent.category.LAUNCHER" category, 这种类型的Intent filter会导致一个icon和标题显示在桌面上,让用户可以启动它并再次返回task.
第二个能力很重要,用户可以离开task后再次点icon返回task,因为这个原因,有两个launchMode标识的Activity总是会初始化一个task, "singleTask" 和 "singleInstance",这两个launchMode只应该在有 ACTION_MAIN和CATEGORY_LAUNCHER filter时使用。想象一下,如果filter缺失会发生什么:一个Intent启动一个singleTask的activity, 初如化一个task,然后用户在task工作了一段时间,用户按下home键,task进入后台不可见。现在用户再也无法返回task,因为他没有出现在launch桌面上。 为了某些原因,你不希望用户可以重新返回Activity, 你可以设置<activity>的属性finishOnTaskLaunch为true.
相关推荐
主要内容涵盖单选题和操作题两大部分。单选题涉及openGauss数据库的基本概念、数据模型、SQL语法、事务管理和用户权限等方面的知识点。操作题则围绕一个名为bookdb的图书购买信息数据库展开,具体任务包括插入图书信息、更新顾客信息、删除购买记录、查询特定图书信息以及创建视图、存储过程和触发器等实际操作。每道题目均附带详细的解题步骤和最终答案。
新建 Microsoft Word 文档 (9).docx
Delphi 12.3控件之nrCommLib Pro v9.54 Full Source for D10.3-D12.7z
内容概要:本文详细介绍了使用三菱PLC FX5U控制四轴伺服系统的全过程,涵盖硬件配置、电气接线、参数设置以及运动控制逻辑。硬件方面,选用三菱FX5U-64MT作为主控制器,搭配四个MR-JE-20A伺服驱动器和其他必要组件。软件部分则深入探讨了轴参数初始化、原点回归、多轴联动、HMI界面设计及报警处理等关键技术环节。特别针对旋转轴的特殊处理进行了详细说明,如双速原点回归、绝对定位指令的应用等。此外,还提供了调试经验和优化技巧,确保系统的高精度和平稳运行。 适合人群:从事自动化控制系统设计、调试的技术人员,尤其是对三菱PLC和伺服系统有一定了解的研发人员。 使用场景及目标:适用于工业自动化领域的四轴伺服控制系统开发,旨在帮助工程师掌握从硬件选型到软件编程的一整套解决方案,提高项目的成功率和技术水平。 其他说明:文中附有多份参考资料,包括完整的程序文件、界面工程、CAD接线图和伺服参数清单,便于读者进行实际操作和验证。
分阶段学习:先掌握基础,再深入细分领域。 理论与实践结合:学完算法后立刻用代码实现。 保持持续学习:AI技术迭代快,需跟踪最新进展。
电子硬件课程设计
Java项目基于ssm框架的课程设计,包含LW+ppt
脚本-压测相关-zyx编写
Java项目基于ssm框架的课程设计,包含LW+ppt
app.mobileconfig
内容概要:本文详细介绍了使用MotorCAD进行2极12槽永磁直流有刷电机的设计与优化方法。首先,通过Python脚本设置电机的基本参数,如外径、轴向长度、额定转速等。接着,深入探讨了磁钢选型、绕组设置、电磁仿真、热分析等多个关键技术环节。针对常见的设计难题,如齿槽转矩、磁钢充磁方向、绕组跨距等提供了具体的解决方案。同时,还分享了一些提高仿真精度和优化性能的实用技巧,如参数扫描、FEA计算、热管理等。最后,通过实测数据分析验证了设计方案的有效性。 适合人群:电机设计工程师、高校相关专业师生、对电机设计感兴趣的开发者。 使用场景及目标:适用于需要精确设计和优化小型永磁直流有刷电机的场合,帮助用户掌握MotorCAD的具体应用,提高设计效率和产品质量。 其他说明:文中提供的Python和VB脚本示例有助于自动化参数设置和批量处理任务,减少重复劳动。此外,还强调了在设计过程中需要注意的关键技术和常见陷阱,确保设计方案的可行性和可靠性。
内容概要:本文详细介绍了三相逆变器在MATLAB/Simulink环境下的PI闭环控制及解耦控制的实现方法。首先,通过坐标变换将三相电流从静止坐标系转换到旋转坐标系,确保功率守恒并实时更新转子位置角。接着,实现了带有抗饱和处理的PI控制器,防止积分风-up现象。然后,针对d轴和q轴之间的耦合问题,引入了解耦控制,通过低通滤波和交叉耦合项来稳定系统。此外,还讨论了PWM生成模块的死区时间和仿真结果的验证方法,强调了参数调试的重要性和具体策略。 适合人群:电力电子工程师、自动化控制领域的研究人员以及对三相逆变器控制感兴趣的高校师生。 使用场景及目标:适用于需要深入了解三相逆变器控制原理和技术实现的研究项目或工程应用。主要目标是掌握PI控制器的设计、解耦控制的应用及其在MATLAB/Simulink中的仿真实现。 其他说明:文中提供了详细的代码示例和调试技巧,帮助读者更好地理解和实践相关理论。同时提醒读者,仿真成功并不代表实际硬件运行无误,建议在实验过程中准备必要的保护措施。
58面经面试过程和题目.txt
OceanBase OBCP 实验指导手册V1.3
内容概要:本文详细介绍了ABB喷涂机器人IRC5P与PLC通过Profinet通讯进行程序号启动的具体步骤和注意事项。主要内容涵盖Profinet通讯的基本配置,包括设备名称、IP地址设置,RAPID代码编写,任务声明,信号映射,以及调试技巧。文中还分享了许多实际调试中的经验和常见错误,如大小写敏感、IP地址分配、程序号有效性和信号防抖处理等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是负责机器人与PLC通讯配置的技术人员。 使用场景及目标:帮助技术人员正确配置ABB喷涂机器人IRC5P与PLC之间的Profinet通讯,确保程序号能够顺利启动,避免常见的配置错误和调试难题。 其他说明:文章强调了硬件和软件配置相结合的重要性,并提供了详细的代码示例和调试建议,有助于提高系统的稳定性和可靠性。
电子硬件课后习题题目及要求.docx
亲测开源好用的红盟云发卡源码对接支付宝等支持一件搭建,方便建立自己的发卡平台,源码全部开源无加密,可方便而开使用。 测试环境:php7.2+mysql+宝塔面板 安装教程: ①设置public运行目录 ②设置thinkphp伪静态 ③访问域名填写数据库信息根据提示安装
Delphi 12.3控件之MiTeC_System_Information_Component_Suite_15.1.0_Full_Source.7z
Delphi 12.3控件之StyleControls 5.80.7z
内容概要:本文详细介绍了YASKAWA公司生产的输送带同步系统YRC1000的工作原理、应用场景及其优缺点。文中不仅解释了YRC1000通过精确控制各输送带电机的转速和位置来实现同步的方法,还展示了Python和C++两种编程语言下的模拟代码片段,帮助理解同步控制的具体实现方式。此外,文章深入探讨了YRC1000在实际应用中的优势,如高同步精度、良好的稳定性和强大的技术支持,同时也指出了其较高的成本和技术门槛。为了提高系统的可靠性和性能,作者分享了一些实用技巧,包括正确的硬件连接、合理的参数设置以及有效的故障排查方法。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些负责生产线设计、维护和优化的专业人士。 使用场景及目标:适用于需要确保多个输送带之间保持高度一致性的场合,如电子产品组装车间、汽车制造工厂等。主要目的是提升生产效率,减少因同步问题导致的质量缺陷或停工现象。 其他说明:尽管YRC1000具有出色的性能表现,但在实际部署过程中仍需注意成本控制和技术细节的把握。文中提供的经验和建议有助于降低实施难度并提高成功率。