在开发中会涉及到多个activity之间的跳转,或者其他应用可复用的activity,例如我们可能希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。就要为Activity配置特定的加载模式,而不是使用默认的加载模式
设置启动模式的位置在 AndroidManifest.xml 文件中 Activity 元素的 android:launchMode 属性。
1.standard模式代码演示
这种模式不用在配置android:launchMode属性,默认即可。
创建一个FirstActivity,演示一下标准的启动模式,代码如下:
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
TextView tv = (TextView) findViewById(R.id.tv);
//展示当前activity实例序列号
tv.setText(this.toString());
Button bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(FirstActivity.this,FirstActivity.class));
}
});
}
}
点击Button用于跳转到下一个FirstActivity界面,然后我们连续三次点击按钮,将会出现下面的现象:
我们注意到同样是FirstActivity的实例,但每次点击后实例号发生了变化,我们持续后退两次,才能退回到第一个FirstActivity。standard模式的原理如下图所示:
如图所示,每次跳转系统都会在Task中生成一个新的FirstActivity实例,并且放于栈顶,按下后退键时才能看到原来的实例。
这种默认模式,不管有没有已存在的实例,都会生成新的实例。
简单点理解:standard启动模式Activity栈从栈底到栈顶顺序为A1 -> B -> C -> A2…。(其中A、B、C等都表示不同的Activity实例,A1、A2则表示属于具有同一Activity类的不同实例)
2.singleTop模式
我们在上面的基础为指定属性android:launchMode=”singleTop”,系统会按照singleTop启动模式处理跳转行为。我们重复几个动作,会出现下面的现象:
我们发现三次FirstActivity的实例号没有变化,说明使用的同一个FirstActivity实例,如果按一下后退键,程序会立即退出,说明当前栈结构中只有一个Activity实例。原理如图所示:
上图所示,跳转时系统会先在栈结构中查找是否存在FirstActivity的实例,如果有会直接使用,不会生成新的实例。
上面我们演示了栈中只有一个Activity,如果多个呢?如果不是在栈顶如何?我们下面通过在同一个示例再演示一下。
再新建一个Activity命名为SecondActivity,代码如下:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
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(SecondActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
}
将FirstActivity跳转代码改为跳转到SecondActivity,点击按钮如图所示结果:
我们发现再从SecondActivity跳转到FirstAcitivity后实例值发生了改变,说明生成了新的实例。原理如下图:
singleTop启动模式如果发现实例位于栈顶,会重复使用,不会生成新的实例。
简单点理解,singleTop即表示当前Activity栈中“栈顶唯一”,Activity跳转顺序或standard模式下栈结构如果为:A -> B -> C -> D1 -> D2,则singleTop启动模式为:A -> B -> C -> D1(此时回调D1的onNewIntent()..)。
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实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。
简单点理解,singleTask表示当前Activity栈中“实例唯一”,Activity跳转顺序或standard模式下栈结构如果为:A -> B1 -> C -> D -> B2,则singleTask启动模式为:A -> B1(此时回调onNewIntent()..)**
4.singleInstance
这种启动模式特殊在它会启动一个新的栈结构,将Activity放置于新的栈结构中,并保证不再有其他的Activity实例进入。
我们修改FirstActivity的launchMode=”standard”,SecondActivity的launchMode=”singleInstance”,由于涉及到了多个栈结构,我们需要在每个Activity中显示当前栈结构的id,所以我们为每个Activity添加如下代码:
TextView tvTask = (TextView) findViewById(R.id.tv_taskid);
tvTask.setText("current task id:"+this.getTaskId());
我们发现这两个Activity实例分别被放置在不同的栈结构中,关于singleInstance的原理图如下:
我们看到从FirstActivity跳转到SecondActivity时,重新启用了一个新的栈结构,来放置SecondActivity实例,然后按下后退键,再次回到原始栈结构;图中下半部分显示的在SecondActivity中再次跳转到FirstActivity,这个时候系统会在原始栈结构中生成一个FirstActivity实例,然后回退两次,注意,并没有退出,而是回到了SecondActivity,为什么呢?第一次按Back键首先是在当前Activity栈中将栈顶元素出栈,然后显示当前Activity栈中下一个Activity栈,然后再按下Back键,不是回到手机桌面,而是回到另一个Activity栈中的SecondActivityInstance,在于“最近栈”,只要此栈位于上次Home操作之后,就会先显示它。
如果我们修改FirstActivity的launchMode值为singleTop、singleTask、singleInstance中的任意一个,流程将会如图所示:
**简单点理解,singleInstance所标识的Activity,当被启动时,系统会首先判断系统其他栈中是否已经存在此Activity实例,有则直接使用,并且其所在的Activity栈理论上只有它一个Activity元素。所以启动它的Activity与它并不在一个task中,所以才需要特别注意Back的问题。一般表示为:task1 A -> task2 B。
singleInstance表示该Activity在系统范围内“实例唯一”。由此我们发现,singInstance和singleTask主要区别在与系统范围内的“实例唯一”还是当前Activity栈“实例唯一”。
**
singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。从外界可能多次跳转到一个界面
singleTask适合作为程序入口点。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。之前打开过的页面,打开之前的页面就ok,不再新建
singleInstance适合需要与程序分离开的页面。例如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。某个应用中用到了google地图,当退出该应用的时候,进入google地图,还是刚才的界面。