Activity 的启动模式都有哪些以及各自的特点

Activity 的启动模式都有哪些以及各自的特点
启动模式(launchMode) 在多个 Activity 跳转的过程中扮演着重要的角色, 它可以决定是否生成新的 Activity 实例,
是否重用已存在的 Activity 实例,是否和其他 Activity 实例公用一个 task 里。这里简单介绍一下 task 的概念,task 
一个具有栈结构的对象,一个 task 可以管理多个 Activity,启动一个应用,也就创建一个与之对应的 task
Activity 一共有以下四种 launchMode
1.standard
2.singleTop
3.singleTask
4.singleInstance
我们可以在 AndroidManifest.xml 配置<activity>的 android:launchMode 属性为以上四种之一即可。

下面我们结合实例一一介绍这四种 lanchMode:

1 standard
standard 模式是默认的启动模式,不用为<activity>配置 android:launchMode 属性即可,当然也可以指定值
为 standard。
我们将创建一个 Activity,命名为 FirstActivity,来演示一下标准的启动模式。FirstActivity 代码如下:
public class FirstActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
FirstActivity 界面中的 TextView 用于显示当前 Activity 实例的序列号, Button 用于跳转到下一个 FirstActivity 界面。
然后我们连续点击几次按钮,将会出现下面的现象:



我们注意到都是 FirstActivity 的实例, 但序列号不同, 并且我们需要连续按后退键两次, 才能回到第一个 FirstActivity。
standard 模式的原理如下图所示:
如图所示,每次跳转系统都会在 task 中生成一个新的 FirstActivity 实例,并且放于栈结构的顶部,当我们按下后退键
时,才能看到原来的 FirstActivity 实例。
这就是 standard 启动模式,不管有没有已存在的实例,都生成新的实例。



2 singleTop
我们在上面的基础上为<activity>指定属性 android:launchMode="singleTop",系统就会按照 singleTop 启
动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象:

我们看到这个结果跟 standard 有所不同,三个序列号是相同的,也就是说使用的都是同一个 FirstActivity 实例;
如果按一下后退键,程序立即退出,说明当前栈结构中只有一个 Activity 实例。singleTop 模式的原理如下图所示:
正如上图所示,跳转时系统会先在栈结构中寻找是否有一个 FirstActivity 实例正位于栈顶,如果有则不再生成新的,
而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个 Activity,如果是多个 Activity 怎么办,如果不是在栈
顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。
我们再新建一个 Activity 命名为 SecondActivity,如下:

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
然后将之前的 FirstActivity 跳转代码改为:
Intent intent = new Intent(FirstActivity.this, SecondActivity.clas
s);
startActivity(intent);
这时候,FirstActivity 会跳转到 SecondActivity,SecondActivity 又会跳转到 FirstActivity。演示结果如下:

我们看到,两个 FirstActivity 的序列号是不同的,证明从 SecondActivity 跳转到 FirstActivity 时生成了新的
FirstActivity 实例。原理图如下:
我们看到,当从 SecondActivity 跳转到 FirstActivity 时,系统发现存在有 FirstActivity 实例,但不是位于栈顶,
于是重新生成一个实例。
这就是 singleTop 启动模式,如果发现有对应的 Activity 实例正位于栈顶,则重复利用,不再生成新的实例。

3 singleTask
在上面的基础上我们修改 FirstActivity 的属性 android:launchMode="singleTask"。演示的结果如下:

我们注意到,在上面的过程中,FirstActivity 的序列号是不变的,SecondActivity 的序列号却不是唯一的,说明
从 SecondActivity 跳转到 FirstActivity 时,没有生成新的实例,但是从 FirstActivity 跳转到 SecondActivity 时生成
了新的实例。singleTask 模式的原理图如下图所示:
在图中的下半部分是 SecondActivity 跳转到 FirstActivity 后的栈结构变化的结果,我们注意到,SecondActivity
消失了,没错,在这个跳转过程中系统发现有存在的 FirstActivity 实例,于是不再生成新的实例,而是将 FirstActivity
之上的 Activity 实例统统出栈, 将 FirstActivity 变为栈顶对象, 显示到幕前。 也许朋友们有疑问, 如果将 SecondActivity
也设置为 singleTask 模式,那么 SecondActivity 实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次
从 SecondActivity 跳转到 FirstActivity 时,SecondActivity 实例都被迫出栈,下次等 FirstActivity 跳转到SecondActivity 时,找不到存在的 SecondActivity 实例,于是必须生成新的实例。但是如果我们有 ThirdActivity,
让 SecondActivity 和 ThirdActivity 互相跳转,那么 SecondActivity 实例就可以保证唯一。
这就是 singleTask 模式,如果发现有对应的 Activity 实例,则使此 Activity 实例之上的其他 Activity 实例统统出
栈,使此 Activity 实例成为栈顶对象,显示到幕前。

4 singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将 Activity 放置于这个新的栈结构中,并保证不再有其
他 Activity 实例进入。
我们修改 FirstActivity 的 launchMode="standard",SecondActivity 的 launchMode="singleInstance",由
于涉及到了多个栈结构,我们需要在每个 Activity 中显示当前栈结构的 id,所以我们为每个 Activity 添加如下代码:
TextView taskIdView = (TextView) findViewById(R.id.taskIdView);
taskIdView.setText("current task id: " this.getTaskId());
然后我们再演示一下这个流程:

我们发现这两个 Activity 实例分别被放置在不同的栈结构中,关于 singleInstance 的原理图如下
我们看到从 FirstActivity 跳转到 SecondActivity 时,重新启用了一个新的栈结构,来放置 SecondActivity 实例,
然后按下后退键,再次回到原始栈结构;图中下半部分显示的在 SecondActivity 中再次跳转到 FirstActivity,这个时
候系统会在原始栈结构中生成一个 FirstActivity 实例, 然后回退两次, 注意, 并没有退出, 而是回到了 SecondActivity,
为什么呢?是因为从 SecondActivity 跳转到 FirstActivity 的时候,我们的起点变成了 SecondActivity 实例所在的栈
结构,这样一来,我们需要“回归”到这个栈结构。
如果我们修改 FirstActivity 的 launchMode 值为 singleTop、singleTask、singleInstance 中的任意一个,流程将会
如图所示:

singleInstance 启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个 share 应用,
其中的 ShareActivity 是入口 Activity,也是可供其他应用调用的 Activity,我们把这个 Activity 的启动模式设置为
singleInstance,然后在其他应用中调用。我们编辑 ShareActivity 的配置:
<

standard 模式是默认的启动模式,不用为<activity>配置 android:launchMode 属性即可,当然也可以指定值
为 standard。
我们将创建一个 Activity,命名为 FirstActivity,来演示一下标准的启动模式。FirstActivity 代码如下:
public class FirstActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
FirstActivity 界面中的 TextView 用于显示当前 Activity 实例的序列号, Button 用于跳转到下一个 FirstActivity 界面。
然后我们连续点击几次按钮,将会出现下面的现象:

我们注意到都是 FirstActivity 的实例, 但序列号不同, 并且我们需要连续按后退键两次, 才能回到第一个 FirstActivity。
standard 模式的原理如下图所示:
如图所示,每次跳转系统都会在 task 中生成一个新的 FirstActivity 实例,并且放于栈结构的顶部,当我们按下后退键
时,才能看到原来的 FirstActivity 实例。
这就是 standard 启动模式,不管有没有已存在的实例,都生成新的实例。2 singleTop
我们在上面的基础上为<activity>指定属性 android:launchMode="singleTop",系统就会按照 singleTop 启
动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象:

我们看到这个结果跟 standard 有所不同,三个序列号是相同的,也就是说使用的都是同一个 FirstActivity 实例;
如果按一下后退键,程序立即退出,说明当前栈结构中只有一个 Activity 实例。singleTop 模式的原理如下图所示:
正如上图所示,跳转时系统会先在栈结构中寻找是否有一个 FirstActivity 实例正位于栈顶,如果有则不再生成新的,
而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个 Activity,如果是多个 Activity 怎么办,如果不是在栈
顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。
我们再新建一个 Activity 命名为 SecondActivity,如下:

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
然后将之前的 FirstActivity 跳转代码改为:
Intent intent = new Intent(FirstActivity.this, SecondActivity.clas
s);
startActivity(intent);
这时候,FirstActivity 会跳转到 SecondActivity,SecondActivity 又会跳转到 FirstActivity。演示结果如下:

我们看到,两个 FirstActivity 的序列号是不同的,证明从 SecondActivity 跳转到 FirstActivity 时生成了新的
FirstActivity 实例。原理图如下:
我们看到,当从 SecondActivity 跳转到 FirstActivity 时,系统发现存在有 FirstActivity 实例,但不是位于栈顶,
于是重新生成一个实例。
这就是 singleTop 启动模式,如果发现有对应的 Activity 实例正位于栈顶,则重复利用,不再生成新的实例。
3 singleTask
在上面的基础上我们修改 FirstActivity 的属性 android:launchMode="singleTask"。演示的结果如下:

我们注意到,在上面的过程中,FirstActivity 的序列号是不变的,SecondActivity 的序列号却不是唯一的,说明
从 SecondActivity 跳转到 FirstActivity 时,没有生成新的实例,但是从 FirstActivity 跳转到 SecondActivity 时生成
了新的实例。singleTask 模式的原理图如下图所示:
在图中的下半部分是 SecondActivity 跳转到 FirstActivity 后的栈结构变化的结果,我们注意到,SecondActivity
消失了,没错,在这个跳转过程中系统发现有存在的 FirstActivity 实例,于是不再生成新的实例,而是将 FirstActivity
之上的 Activity 实例统统出栈, 将 FirstActivity 变为栈顶对象, 显示到幕前。 也许朋友们有疑问, 如果将 SecondActivity
也设置为 singleTask 模式,那么 SecondActivity 实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次
从 SecondActivity 跳转到 FirstActivity 时,SecondActivity 实例都被迫出栈,下次等 FirstActivity 跳转到SecondActivity 时,找不到存在的 SecondActivity 实例,于是必须生成新的实例。但是如果我们有 ThirdActivity,
让 SecondActivity 和 ThirdActivity 互相跳转,那么 SecondActivity 实例就可以保证唯一。
这就是 singleTask 模式,如果发现有对应的 Activity 实例,则使此 Activity 实例之上的其他 Activity 实例统统出
栈,使此 Activity 实例成为栈顶对象,显示到幕前。


4 singleInstance

这种启动模式比较特殊,因为它会启用一个新的栈结构,将 Activity 放置于这个新的栈结构中,并保证不再有其
他 Activity 实例进入。
我们修改 FirstActivity 的 launchMode="standard",SecondActivity 的 launchMode="singleInstance",由
于涉及到了多个栈结构,我们需要在每个 Activity 中显示当前栈结构的 id,所以我们为每个 Activity 添加如下代码:
TextView taskIdView = (TextView) findViewById(R.id.taskIdView);
taskIdView.setText("current task id: " this.getTaskId());
然后我们再演示一下这个流程:

我们发现这两个 Activity 实例分别被放置在不同的栈结构中,关于 singleInstance 的原理图如下
我们看到从 FirstActivity 跳转到 SecondActivity 时,重新启用了一个新的栈结构,来放置 SecondActivity 实例,
然后按下后退键,再次回到原始栈结构;图中下半部分显示的在 SecondActivity 中再次跳转到 FirstActivity,这个时
候系统会在原始栈结构中生成一个 FirstActivity 实例, 然后回退两次, 注意, 并没有退出, 而是回到了 SecondActivity,
为什么呢?是因为从 SecondActivity 跳转到 FirstActivity 的时候,我们的起点变成了 SecondActivity 实例所在的栈
结构,这样一来,我们需要“回归”到这个栈结构。
如果我们修改 FirstActivity 的 launchMode 值为 singleTop、singleTask、singleInstance 中的任意一个,流程将会
如图所示:

singleInstance 启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个 share 应用,
其中的 ShareActivity 是入口 Activity,也是可供其他应用调用的 Activity,我们把这个 Activity 的启动模式设置为
singleInstance,然后在其他应用中调用。我们编辑 ShareActivity 的配置:
<activity

一个启动模式为 singleTop 的 activity, 如果再试图启动会怎样? 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值