Activity启动模式一

本文详细探讨了Android中Activity的四种启动模式:Standard、SingleTop、SingleTask和SingleInstance,以及它们对任务栈的影响。重点讲解了每种模式的特点、应用场景,并通过实例分析了它们在任务栈中的行为。此外,还讨论了android:taskAffinity属性和allowTaskReparenting属性的使用场景,以及在特定情况下的Activity迁移和任务栈切换。
摘要由CSDN通过智能技术生成

众所周知,Activity有4种启动模式,分别是:Standard、SingleTop、SingleTask和SingleInstance,它们控制了被启动Activity的启动行为。本文将通过具体案例,详细分析这几种模式的差异和使用场景,方便日后查阅。

在展开具体分析之前,我们首先要了解下两个基础知识:Activity任务栈和android:taskAffinity属性。

基础知识

Activity任务栈(Task)

Activity任务栈(Task)是一个标准的栈结构,具有“First In Last Out”的特性,用于在ActivityManagerService侧管理所有的Activity(AMS通过TaskRecord标识一个任务栈,通过ActivityRecord标识一个Activity)。

每当我们打开一个Activity时,就会有一个Activity组件被添加到任务栈,每当我们通过“back”键退出一个Activity时,就会有一个Activity组件从任务栈出栈。任意时刻,只有位于栈顶的Activity才可以跟用户进行交互。

同一时刻,Android系统可以有多个任务栈;每个任务栈可能有一个或多个Activity,这些Activity可能来自于同一个应用程序,也可能来自于多个应用程序。另外,同一个Activity可能只有一个实例,也可能有多个实例,而且这些实例既可能位于同一个任务栈,也可能位于不同的任务栈。而这些行为都可以通过Activity启动模式进行控制。

在Android系统的多个任务栈中,只有一个处于前台,即前台任务栈,其它的都位于后台,即后台任务栈。后台任务栈中的Activity处于暂停状态,用户可以通过唤起后台任务栈中的任意Activity,将后台任务栈切换到前台。

android:taskAffinity属性

android:taskAffinity是Activity的一个属性,表示该Activity期望的任务栈的名称。默认情况下,一个应用程序中所有Activity的taskAffinity都是相同的,即应用程序的包名。当然,我们可以在配置文件中为每个Activity指定不同的taskAffinity(只有和已有包名不同,才有意义)。一般情况下,该属性主要和SingleTask启动模式或者android:allowTaskReparenting属性结合使用(下面会详细介绍),在其他情况下没有意义。

四种启动模式

上面简要介绍了Activity任务栈和android:taskAffinity属性。有了这些基础之后,我们就可以详细介绍Activity的四种启动模式了。

一般情况下,我们在AndroidManifest配置文件中,为Activity指定启动模式和taskAffinity,如下所示:

<activity 
android:name="leon.com.activitylaunchmode.FirstActivity" 
android:launchMode="singleTop"
android:taskAffinity="leon.com.activitylaunchmode1"/>

除此之外,我们也可以通过设置Intent的某些标志位来达到相同的效果,关于这些和Activity启动模式相关的标志位,我们会在下篇文章进行介绍。

Standard

标准模式,也是系统的默认模式。该模式下,每次启动Activity,都会创建一个新实例,并且将其加入到启动该Activity的那个Activity所在的任务栈中,所以目标Activity的多个实例可以位于不同的任务栈。例如:ActivityA启动了标准模式的ActivityB,那么ActivityB就会在ActivityA所在的任务栈中。

关于标准模式的Activity,有一个很经典的异常:
当我们通过非Activity的Context(例如:Service)启动标准模式的Activity时,就会有以下异常:

Caused by: Android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

这是因为标准模式的Activity会进入启动它的Activity的任务栈中,但是非Activity的Context又没有任务栈,所以就出错了。解决方案在异常信息中已经给出了:在Intent中添加FLAG_ACTIVITY_NEW_TASK标志位,这样就会为目标Activity创建新的任务栈。

OK,下面我们通过示例验证下该启动模式,具体步骤如下所示:

  1. 创建MainActivity,并且在MainActivity的onCreate方法中,打印出当前Activity所在的任务栈ID。
  2. 设置MainActivity的启动模式为Standard。
  3. 然后通过MainActivity不断启动MainActivity本身。

经过上述步骤,最终的任务栈如下所示(adb shell dumpsys activity activities):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u6L14bET-1571788241427)(http://ltlovezh.com/Standard模式.png)]

通过MainActivity打印出的日志如下所示:
[外链图片转存失败,源站可能有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值