本文使您彻底了解Activity的启动模式和任务堆栈

电脑杂谈  发布时间:2020-04-03 10:03:24  来源:网络整理

activity栈_activity task任务栈_activity 启动activity

作者: 尹星

博客:

活动的启动模式和任务堆栈是Android的关键和难点. 它们也是Android面试的必修知识点. 即使已经从事Android开发多年,许多学生也可能无法完全理解. 鲜为人知. 本文使您彻底了解Android中Activity的启动模式和任务堆栈!

前言

应用程序通常包含许多活动,每个活动都是具有特定功能且可以由用户操作的组件. 此外,活动可以彼此启动,并且当前应用程序的活动甚至可以启动其他应用程序的活动.

例如,如果您的应用程序要发送电子邮件,则可以使用“发送”操作定义一个Intent,并传递一些数据,例如对方的电子邮件地址和电子邮件的内容. 这样,如果另一个应用程序中的活动声明可以响应此Intent,则该活动将被打开. 发送电子邮件后,按回车键仍会返回到您的应用程序,这使用户看起来好像刚才编写电子邮件的活动是您应用程序的一部分.

因此,即使来自不同应用程序的许多活动,Android系统仍可以无缝地将它们组合在一起.

那么这一切是怎么发生的?这将讨论本文将介绍的Activity任务堆栈和Activity启动模式.

什么是任务堆栈?

任务堆栈任务是用于放置Activity实例的容器. 它以堆栈的形式保存,即所谓的先进先出. 有两个基本操作: 推入和弹出. 存储的活动不支持重新排序,只能根据推送和弹出操作更改活动的顺序.

启动应用程序时,系统默认会为根活动创建一个相应的任务. 默认情况下,已启动的活动将放置在同一任务中,新启动的活动将被推入启动并显示该活动的堆栈中. 当用户按下“后退”按钮时,该活动将从堆栈中弹出,按下“主页”按钮返回到桌面,然后启动另一个应用程序. 这时,任务将被移至后台并成为后台任务堆栈. 任务被转移到前台,并成为前台任务堆栈. Android系统会在前台任务堆栈中显示“顶级实例活动”.

任务堆栈的作用

过去,基于应用程序(application)程序的开发,程序具有明确的界限. 程序是一个应用程序. 应用程序可以使用新线程甚至新进程来实现功能. 但是,该应用程序和该应用程序不能重复. 具有资源和功能.

activity栈_activity 启动activity_activity task任务栈

Android引入了基于组件开发的软件架构. 尽管我们开发了android程序,但仍然使用apk项目和Application开发形式,但是对于Aplication的开发,我们使用四个主要组件: 活动和服务. 组件可以跨应用程序重用. 这是android的魔力.

尽管可以在应用程序中调用组件,但是组件所在的过程必须处于该组件所在的Aplication进程中. 由于android增强了组件的概念而削弱了Aplication的概念,因此在android程序的开发中,如果A应用程序的A组件要使用拍照或录像功能,则不必为Camera类开发,并直接呼叫系统随附的相机. 应用程序中的组件(称为其B应用程序)(称为其B组件)很好.

但这带来了一个新问题. A组件在A应用程序中运行,而B组件在B应用程序中运行. 自然,它们不在同一过程中. 从B组件返回时,如何正确返回到A组件呢?任务负责实现此功能,它是从用户的角度建立的抽象概念,用于理解应用程序. 因为用户可以看到的组件是Activity,所以Task可以理解为实现功能,并负责管理所有使用过的Activity实例的堆栈.

堆栈是先进先出线性表. 活动的状态是根据活动在当前堆栈结构中的位置确定的. 在正常情况下activity栈,当一个活动启动另一个活动时,新启动的活动将放置在任务堆栈的顶部并处于活动状态,而启动该活动的活动将成功保留在任务堆栈中. ,在停止状态下,当用户按下返回键或调用finish()方法时,系统将删除顶部的Activity,并让后续的Activity恢复活动状态. 当然,世界不可能总是那么“和谐”. 您可以为活动设置一些“特权”以打破这种“和谐”模式. 这种特权由AndroidManifest文件中的属性andorid: launchMode或通过Intent设置. 为了设置该标志,下面介绍了Activity的几种启动模式.

标准

默认模式,您无需编写配置. 在这种模式下,默认情况下会创建一个新实例. 因此,在这种模式下,可以有多个相同的实例,并且也可以允许多个相同的活动重叠. 应用场景: 大多数活动.

如果跨进程调用以这种方式启动的Activity,则5.0之前新启动的Activity实例将被放置在发送Intent的Task堆栈的顶部,即使它们属于不同的程序,这似乎有些令人困惑. 不太合理,因此在5.0之后,上述方案将创建一个新的Task,并将新启动的Activity放入刚刚创建的Task中,这更加合理.

singleTop

栈顶重用模式. 如果要启动的活动已经存在于任务堆栈的顶部,则不会创建新实例,但是将调用onNewIntent()方法. 避免在堆栈顶部创建重复的活动. 应用程序场景: 单击通知栏中收到的通知,然后您需要启动一个活动. 该活动可以使用singleTop,否则每次单击都会创建一个新的活动. 当然,在实际的开发过程中,测试姐妹文章可能给您带来了如下错误: 在场景中,连续快速单击以启动两个活动. 如果此时要启动的活动使用singleTop模式,则也可以避免此错误.

与标准模式相同. 如果外部程序启动了singleTop活动,则Android 5.0之前的新创建的Activity将被放置在调用者的任务中,而5.0及更高版本将被放置在新任务中.

singleTask

activity task任务栈_activity 启动activity_activity栈

在堆栈重用模式下,活动在任务堆栈中将只有一个实例. 如果任务堆栈中已经存在要激活的活动,则不会创建新的活动. 相反,现有活动将被重用,onNewIntent()方法将被调用,活动任务堆栈上的所有活动将被清除. 应用程序场景: 大多数应用程序的主页. 对于大多数应用程序,当我们单击主界面上的后退按钮以退出应用程序时,然后当我们首次进入主界面时,主界面位于堆栈的底部. 不管我们将来打开多少活动,只要我们再次打开主界面,都应该使用删除主界面活动中所有活动的方法,使主界面活动位于堆栈顶部,而不是在堆栈顶部添加主接口“活动”的新实例,而是通过这种方式确保退出时所有活动都可以被销毁.

当跨应用程序Intent传递时,如果系统中不存在singleTask Activity实例,则将创建一个新Task,然后将创建SingleTask Activity实例并将其放置在新Task中.

1: 如果任务堆栈T1当前为ABC,此时ActivityD请求以singleTask模式启动,并且其所需的任务堆栈恰好为T1,那么系统将直接创建D的实例并将其放在堆栈上转到T1.

2: 如果DActivity启动所需的任务堆栈为T2,则由于T2和D实例都不存在,因此系统将首先创建任务堆栈T2activity栈,然后创建D的实例并将其推入T2. 我们可以通过设置Activity的taskAffinity属性来模拟这种情况.

3: 如果D所需的任务堆栈为T3,而当前任务堆栈T3为ADBC,则根据堆栈内重用的原理,此时将不会重新创建D,系统将切换D到栈顶并调用其onNewIntent()方法. 同时,singleTask默认具有ClearTop的效果,这将导致堆栈中D上的所有活动弹出堆栈,因此最终的T3情况是AD.

4: 如果当前有两个任务堆栈,则前台任务堆栈T4的状态为AB,而后台任务堆栈t4带有CD. 假设CD的启动模式为singleTask,则现在使用B来启动D,然后将整个后台任务切换到前台,此时整个堆栈变成ABCD.

5: 如果上述其他条件相同,则B以C而不是D开头,因此整个堆栈变为ABC,因为D在C上,并且将从堆栈中清除.

activity task任务栈_activity栈_activity 启动activity

singleInstance

在单实例模式下,整个手机操作系统中仅存在一个实例. 不同的应用程序打开此活动并共享相同的通用活动. 他将在自己的独立任务堆栈中运行,并且任务堆栈中仅存在他的一个实例. 应用场景: 调用入接口. 这种使用模式相对较少,可以在Launcher中使用. 或者您确定只需要创建一个活动实例. 谨慎使用.

设置意图标志

系统提供了两种方法来设置活动的启动方式. 除了在AndroidManifest文件中进行设置外,您还可以通过Intent Flag设置Activity的启动模式. 下面我们简要介绍一些标志.

FLAG_ACTIVITY_NEW_TASK

使用新任务来启动活动,但是启动的每个活动都在新任务中. 标志通常用于从服务启动活动的情况. 由于服务中不存在活动堆栈,因此该标志用于创建新的活动堆栈和创建新的活动实例.

FLAG_ACTIVITY_SINGLE_TOP

使用单顶模式启动活动与指定android具有相同的效果: launchMode =“ singleTop”.

FLAG_ACTIVITY_CLEAR_TOP

使用SingleTask模式启动Activity与指定android具有相同的效果: launchMode =“ singleTask”.

FLAG_ACTIVITY_NO_HISTORY

活动使用此模式启动活动. 当该活动开始另一个活动时,该活动将消失并且不会保留在活动堆栈中.

activity栈_activity task任务栈_activity 启动activity

LaunchMode和StartActivityForResult

在开发过程中,我们经常使用StartActivityForResult方法启动一个Activity,然后您可以在onActivityResult()方法中接收上一页的返回值,但是您可能会遇到无法获得该返回值的情况值可能是因为Activity的LaunchMode设置为singleTask. 在5.0之后,Android的LaunchMode和StartActivityForResult之间的关系已更改. 现在,两个活动A和B从页面A跳转到页面B,并查看LaunchMode和StartActivityForResult之间的关系:

这是为什么?

这是因为在5.0中修改了ActivityStackSupervisor类中的startActivityUncheckedLocked方法. 在5.0之前的版本中,启动活动时,系统将首先检查活动的launchMode. 如果将A页面设置为SingleInstance或将B页面设置为singleTask或singleInstance,则FLAG_ACTIVITY_NEW_TASK标志将添加到LaunchFlags,并且如果包含FLAG_ACTIVITY_NEW_TASK标志,onActivityResult将立即收到cancle消息,并且此方法自5.0起已被修改. 修改后,即使启动页面的启动模式设置为singleTask或singleInstance,onActivityResult仍然可以正常工作,也就是说,无论设置了哪种启动模式,StartActivityForResult与onActivityResult()的组合都是有效的. 因此,如果您当前正在基于5.0进行相关开发,请不要忘记向后兼容. 这里有一个坑,请避免.

摘要

在实际的开发过程中,如果使用更合理的Activity启动模式来管理任务堆栈,则可以事半功倍. 在选择launchMode之前,我们必须首先了解当前Activity的角色和实际使用场景,以便做出合理的选择.

参考阅读

探索Android开发的艺术

Android内核剖析

Android Group Heroes

返回搜狐,查看更多


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-162303-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...