Activity的启动模式解析

最近在面试被问到Activity的启动模式,虽然能说上它们四个的区别,但是实际使用还是有点模糊,索性再一次认真的看了一下Android开发官方文档的讲解,理解了,特意记录一下,以便后面查阅。
一.Activity的启动模式有四种:

1.”standard”(默认模式)

默认,系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。

总结:
由于返回栈中的 Activity 永远不会重新排列,因此如果应用允许用户从多个 Activity 中启动特定 Activity,则会创建该 Activity 的新实例并推入堆栈中(而不是将 Activity 的任一先前实例置于顶部)。 因此,应用中的一个 Activity 可能会多次实例化(即使 Activity 来自不同的任务),如图 3 所示。 因此,如果用户使用“返回”按钮向后导航,则会按 Activity 每个实例的打开顺序显示这些实例(每个实例的 UI 状态各不相同)。 但是,如果您不希望 Activity 多次实例化,则可修改此行为。
如图:
一个 Activity 将多次实例化
这里写图片描述

2.”singleTop”

如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。
例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 “standard” 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 “singleTop”,则 D 的现有实例会通过 onNewIntent() 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 A 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 “singleTop” 也是如此。

注:为某个 Activity 创建新实例时,用户可以按“返回”按钮返回到前一个 Activity。 但是,当 Activity 的现有实例处理新 Intent 时,则在新 Intent 到达 onNewIntent() 之前,用户无法按“返回”按钮返回到 Activity 的状态。

举两个例子:
设置singleTop和singleTask情况2) 3)一样的条件下,结果都和singleTask中的2)的结果一样

3.”singleTask”

系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
注:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。

我们再来看另一示例,Android 浏览器 应用声明 Web 浏览器 Activity 应始终在其自己的任务中打开(通过在 <activity> 元素中指定 singleTask 启动模式)。这意味着,如果您的应用发出打开 Android 浏览器的 Intent,则其 Activity 与您的应用位于不同的任务中。相反,系统会为浏览器启动新任务,或者如果浏览器 已有任务正在后台运行,则会将该任务上移一层以处理新 Intent。

无论 Activity 是在新任务中启动,还是在与启动 Activity 相同的任务中启动,用户按“返回”按钮始终会转到前一个 Activity。 但是,如果启动指定 singleTask 启动模式的 Activity,则当某后台任务中存在该 Activity 的实例时,整个任务都会转移到前台。此时,返回栈包括上移到堆栈顶部的任务中的所有 Activity。
如图 显示了这种情况。
这里写图片描述
刚才做了一个例子测试了一下:
1)任务栈1里面有两个Activity,Activity_AA,Activity_BB,前提是把这两个Activity都设置成SingleTask模式,然后启动任务栈1,然后点击Activity_AA跳转Activity_BB,此时界面上是Activity_BB,然后点击home键,此时任务栈1回到后台,然后启动任务栈2(也就是第二个工程),任务栈2里面有三个Activity,分别是Activity_A,Activity_B,Activity_C 三个类,点击Activity_A,跳转到Activity_B,点击Activity_B跳转Activity_C,点击Activity_C跳转工程1的Activity_BB,会看到任务栈1从后台跑到了前台,此时界面上显示的是Activity_BB,(即显示了任务栈1中的Activity_BB),当点击硬件返回键时,返回到的是任务栈1中的Activity_AA(即原来在任务栈1中排在Activity_BB下面的Activity_AA),再接着按返回键,明显的看到任务栈1又回到了后台,任务栈2又回到了前台,此时显示的是任务栈2中的Activity_C。

结论:这样效果不是很好,如果要达到从A这个应用启动B应用的一个界面,当B应用中界面显示完成后,点击返回键,理论上应该还是回到A界面,这样就让用户看不到是两个APP间在跳转,实现了APP间的无缝结合。但是如果采用这种B应用的所有界面都采用SingleTask的话,按返回按钮返回的还是B界面的Activiy,直到把B栈中的所有Activity都返回完,才会回到A应用。

2)如果把工程1里面的,Activity_AA(相当于栈底)设置成singleTask,Activity_BB还是默认的启动模式,这样也是点击Activity_AA跳转Activity_BB,此时界面上是Activity_BB,然后点击home键,此时任务栈1回到后台,然后启动任务栈2(也就是第二个工程),任务栈2里面有三个Activity,分别是Activity_A,Activity_B,Activity_C 三个类,点击Activity_A,跳转到Activity_B,点击Activity_B跳转Activity_C,点击Activity_C跳转工程1的Activity_BB,会看到任务栈2中重新启动了一个Activity_BB,此时界面上显示的是Activity_BB,当点击硬件返回键时,返回到的是任务栈2中的Activity_C。这样本身显示的逻辑是对的。

结果:当工程2跳转另一个app中的Activity_BB时候,就会在任务栈2中又创建了一个Activity_BB(因为Activity_BB的模式是默认模式),现在任务栈2中的是:A-B-C-Activity_BB(任务栈1还是Activity_AA,Activity_BB没有变化),这样返回的时候就是一直操作的任务栈2:Activity_BB-C-B-A。

3)同样的,如果把2)的情况调换一下位置即工程1里面的,Activity_AA设置成还是默认的启动模式,Activity_BB设置成singleTask模式。还是跟2)一样的操作的话,结果点击返回键,明显看到任务栈2从后台返回到前台,显示的是任务栈1中的Activity_BB界面,点击返回键,显示的任务栈1中的Activity_AA,再次点击返回键,才回到了任务栈2中的Activity_C.这样也是一般不符合逻辑的。

结果:分析上述情况,明显看到任务栈1里面有Activity_AA,Activity_BB,r任务栈2里面有Activity_A,Activity_B,Activity_C。将Activity_BB设置成了singleTask,当A应用调用B应用的Activity_BB时候,因为BB是singleTask,所以任务栈1重用了,直接返回到前台,排在任务栈2的上面,当返回的时候只有任务栈1里面的Activity返回完以后,才到任务栈2.

4.”singleInstance”。

与 “singleTask” 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值