Activity深入——四种启动模式

无简介

使用manifest文件

当在manifest文件中声明Activity之后,你可以通过Activity节点下面的launchMode属性去具体指定这个Activity是以什么样的方式去与任务连接。 launchMode属性指定了在任务中,这个Activity要以什么样的方式去启动。有四种不同的启动方式可以给launchMode去使用。

1.standard模式

原文:“standard” (the default mode) Default. The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances.

译文:默认的模式。系统在任务中对这个已经运行的Activity新建一个实例并且为它指定一个intent。这个Activity可以被多次实例化,每个实例可以属于不同的任务,但是一个任务可以包括多个实例。

2.singleTop模式

原文:“singleTop” If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance through a call to its onNewIntent() method, rather than creating a new instance of the activity. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances (but only if the activity at the top of the back stack is not an existing instance of the activity).

译文:如果要创建的Activity实例已经在当前的task中存在了,并且位于最顶端,系统将会调用这个实例的onNewIntent方法而不是去给这个activity创建一个新的实例。这个activity可以被实例化多次,每个实例都可以属于不同的task,并且一个task也可以含有多个实例。(但是activity本身就存在实例且本来就在back stack的顶端的时候除外)

原文:For example, suppose a task’s back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default “standard” launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D’s launch mode is “singleTop”, the existing instance of D receives the intent through onNewIntent(), because it’s at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is “singleTop”.

译文:举例,假设一个task的back stack中包含A、B、C、D四个activity,且A为根activity,D在最上面(也就是在栈中,activity的顺序从下到上为ABCD【注:栈是先进后出,类似汉诺塔】).这时一个要打开D的intent来了。如果D的launchMode是"standard"的话,一个D的新的实例将会被创建,并且在栈中,activity的顺序从下到上将变成A-B-C-D-D。如果D的launchMode是"singleTop"的话,已经存在的D的实例将会调用onNewIntent方法来将这个intent送达,应为它本来就在栈的最上方——结果是栈中从下到上为A-B-C-D。如果一个要打开B Activity的intent来了,一个B的新的实例将会被添加到栈中。

原文:Note: When a new instance of an activity is created, the user can press the Back button to return to the previous activity. But when an existing instance of an activity handles a new intent, the user cannot press the Back button to return to the state of the activity before the new intent arrived in onNewIntent().

译文:注意:当一个activity的时候被建立,用户可以按back键返回到上一个activity。 但是当一个已经存在的activity处理一个新intent时,用户不可能按back键回到intent到达activity的onNewIntent()之前的状态。


我写的一个测试代码: activity顺序是(1:)A-B-C-D-B-C-D…或者为(2):A-B-C-D-D-D两种,其中B-D的launchMode设置为了"singleTop"。 下面是两种顺序的栈中的结果

(1):A-B-C-D-B-C-D…
Running activities (most recent first):
TaskRecord{42dd84b8 #125 A cn.sumile.activitylaunchmode U 0}
Run #8: ActivityRecord{43051f68 u0 cn.sumile.activitylaunchmode/.ThreeActivity}
Run #7: ActivityRecord{42c265d0 u0 cn.sumile.activitylaunchmode/.TwoActivity}
Run #6: ActivityRecord{4262fb80 u0 cn.sumile.activitylaunchmode/.oneActivity}
Run #5: ActivityRecord{425efa20 u0 cn.sumile.activitylaunchmode/.ThreeActivity}
Run #4: ActivityRecord{42605898 u0 cn.sumile.activitylaunchmode/.TwoActivity}
Run #3: ActivityRecord{425f35c8 u0 cn.sumile.activitylaunchmode/.oneActivity}
Run #2: ActivityRecord{425ee270 u0 cn.sumile.activitylaunchmode/.MainActivity}
(2):A-B-C-D-D-D
Running activities (most recent first):
TaskRecord{42c0a590 #126 A cn.sumile.activitylaunchmode U 0}
Run #5: ActivityRecord{4262f5c0 u0 cn.sumile.activitylaunchmode/.ThreeActivity}
Run #4: ActivityRecord{42605898 u0 cn.sumile.activitylaunchmode/.TwoActivity}
Run #3: ActivityRecord{425ee270 u0 cn.sumile.activitylaunchmode/.oneActivity}
Run #2: ActivityRecord{4289c370 u0 cn.sumile.activitylaunchmode/.MainActivity}

从上面我们可以看到,如果activity的启动模式为singletop,当这个activity是在栈的最上方(当前显示状态下),那么会调用onNewIntent方法,如果不是,会新创建一个实例然后把这个实例放到最上方。

3.singleTask模式

原文:The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.

译文:系统创建一个新的任务,并且将这个activity作为这个新的task的最底层activity。如果这个activity的实例已经在另一个task中运行,系统会将这个intent发送到这个已存在的实例并调用它的onNewIntent方法,而不是创建一个新的实例。在同一时间,只能存在一个此activity的实例。

原文:Note: Although the activity starts in a new task, the Back button still returns the user to the previous activity.

虽然这个activity开启了一个新的task,但是用户点击back键仍然会返回到上一个activity. 额。。。你信了么? 我没信,于是我做了个实验。(使用命令行,在adb.exe所在位置执行adb shell dumpsys activity)




上面是两个activity,并且我把他们的launchMode都设为了singleTask;然后运行看看结果是什么。

Running activities (most recent first):
TaskRecord{42fc8210 #129 A cn.sumile.activitylaunchmode U 0}
Run #3: ActivityRecord{425f1ce0 u0 cn.sumile.activitylaunchmode/.ThirdActivity}
Run #2: ActivityRecord{425ee270 u0 cn.sumile.activitylaunchmode/.MainActivity}
或是:
Running activities (most recent first):
TaskRecord{426167b8 #130 A cn.sumile.activitylaunchmode U 0}
Run #3: ActivityRecord{425f35c8 u0 cn.sumile.activitylaunchmode/.SecondActivity}
Run #2: ActivityRecord{425f1b90 u0 cn.sumile.activitylaunchmode/.MainActivity}

尼玛,坑爹呢??!! 泡沫破灭之后,开始各种谷百,拜读到一篇:解开Android应用程序组件Activity的"singleTask"之谜 看完之后我们知道了,需要在activity节点下添加一句这个代码:

android:taskAffinity=“cn.sumile.android”//内容随意

这次的结果是:

Running activities (most recent first):
TaskRecord{42fb1500 #133 A cn.sumile.android U 0}
Run #3: ActivityRecord{425f35c8 u0 cn.sumile.activitylaunchmode/.SecondActivity}
TaskRecord{42ebf230 #132 A cn.sumile.activitylaunchmode U 0}
Run #2: ActivityRecord{425ee270 u0 cn.sumile.activitylaunchmode/.MainActivity}

Mission completed~

4.singleInstance模式

原文:“singleInstance”. Same as “singleTask”, except that the system doesn’t launch any other activities into the task holding the instance. The activity is always the single and only member of its task; any activities started by this one open in a separate task.

如果singleTask一样,除了系统之外不启动任何activity到持有其他实例的task中。activity总是单一的并且是它的task的唯一成员,其他任何通过它启动的activity总是在不同的task中。

原文:As another example, the Android Browser application declares that the web browser activity should always open in its own task—by specifying the singleTask launch mode in the element. This means that if your application issues an intent to open the Android Browser, its activity is not placed in the same task as your application. Instead, either a new task starts for the Browser or, if the Browser already has a task running in the background, that task is brought forward to handle the new intent.

译文:另一个例子是,Android的浏览器程序声明,它的activity应该在它自己的task中启动——通过制定它activity节点下的launchMode属性。这意味着如果你的程序发出了一个打开Android浏览器的intent,它的activity和你的程序运行在不同的task中。相反,任何一个新的task中启动Browser,或者这个浏览器已经在后台task中运行了,这个task将会被放到前台来处理这个intent。

原文:Regardless of whether an activity starts in a new task or in the same task as the activity that started it, the Back button always takes the user to the previous activity. However, if you start an activity that specifies the singleTask launch mode, then if an instance of that activity exists in a background task, that whole task is brought to the foreground. At this point, the back stack now includes all activities from the task brought forward, at the top of the stack. Figure 4 illustrates this type of scenario.

译文:不管一个activity是运行在一个新的task或者运行在与启动它的activity相同的task中,back键总是把用户带到前面的activity。如果你开启了一个指定launchMode为singleTask的activity,那么如果这个activity的实例已经后台task中存在了,包含这个activity的整个task将会被带到前台。这时候back stack中包含了这个被带到前台的task中的全部activity,在stack的最顶部。Figure 4 说明了这种情况: diagram_backstack_singletask_multiactivity 慕课网singleInstance讲解 [embed]http://v1.mukewang.com/caacae5d-c18d-415f-ab6c-7b2978ab9484/H.mp4[/embed] [dl href=‘http://pan.baidu.com/s/1mgEHZgW’]本篇测试代码下载[/dl]

-------------本文结束  感谢您的阅读-------------
下次一定