Android活动的启动模式

在实际的项目中,我们应该根据特定的需求为每个活动指定恰当的启动模式。活动的启动模式一共有四种,可以在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。下面我们来逐一介绍:
(1)standard:活动的默认启动模式,在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并置于栈顶的位置。对于使用standard模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
代码实例:

 1 @Override
 2 protected void onCreate(Bundle savedInstanceState) {
 3     super.onCreate(savedInstanceState);
 4     setContentView(R.layout.activity_main);
 5 
 6     Log.d(TAG, this.toString());
 7     btn_jump = findViewById(R.id.btn_jump);
 8     btn_jump.setOnClickListener(new View.OnClickListener() {
 9     @Override
10     public void onClick(View v) {
11         Intent intent = new Intent(MainActivity.this,MainActivity.class);
12         startActivity(intent);
13         }
14     });
15 }

运行程序,然后在连续点击两次跳转按钮,可以看到logcat中打印的信息如下:

从打印的信息我们可以看出,每点击一次按钮就会创建一个新的MainActivity实例。此时返回栈中也会存在三个MainActivity的实例,因此你需要连按3次Back键才能退出程序。

(2)singleTop:在启动活动的时候如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
修改AndroidManifest.xml中MainActivity的启动模式,如下所示:

1 <activity 
2 android:name=".MainActivity"
3 android:launchMode="singleTop">
4 <intent-filter>
5 <action android:name="android.intent.action.MAIN" />
6 
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9 </activity>

运行程序,查看logcat会看到已经创建了一个MainActivity的实例,如图所示:

但是之后不管你点击多少次按钮都不会再有新的打印信息出现,因为目前MainActivity已经处于返回栈的栈顶,每当你想再启动一个MainActivity时都会直接使用栈顶的活动,所以MainActivity也只会有一个实例,仅按一次Back键就可以退出程序。

不过当MainActivity并未处于栈顶位置时,这时再启动MainActivity,还是会创建新的实例的。

(3)singleTask:当活动的启动模式指定为singleTask,每次启动该活动时,系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
修改AndroidManifest.xml中MainActivity的启动模式,如下所示:

1 <activity
2 android:name=".MainActivity"
3 android:launchMode="singleTask">
4 <intent-filter>
5 <action android:name="android.intent.action.MAIN" />
6 
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9 </activity>

然后在MainActivity中添加onRestart()方法,并打印日志:

1 @Override
2 protected void onRestart() {
3     super.onRestart();
4     Log.d("MainActivity","onRestart");
5 }

新建一个activity:JumpActivity,并添加onDestroy()方法,并打印日志:

1 @Override
2 protected void onDestroy() {
3     super.onDestroy();
4     Log.d("JumpActivity","onDestroy");
5 }

在JumpActivity界面布局中添加一个Button控件,添加点击事件使其跳回MainActivity:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3 xmlns:app="http://schemas.android.com/apk/res-auto"
 4 xmlns:tools="http://schemas.android.com/tools"
 5 android:layout_width="match_parent"
 6 android:layout_height="match_parent"
 7 tools:context=".JumpActivity">
 8 
 9     <Button
10     android:text="跳回去玩一下"
11     android:id="@+id/btn_jump_back"
12     android:layout_width="wrap_content"
13     android:layout_height="wrap_content" />
14 
15 </android.support.constraint.ConstraintLayout>
1 Button btn_jump_back = findViewById(R.id.btn_jump_back);
2 btn_jump_back.setOnClickListener(new View.OnClickListener() {
3     @Override
4     public void onClick(View v) {
5     Intent intent = new Intent(JumpActivity.this,MainActivity.class);
6     startActivity(intent);
7     }
8 });

最后修改Button的点击事件,使其跳转到JumpActivity界面:

1 btn_jump.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4     Intent intent = new Intent(MainActivity.this,JumpActivity.class);
5     startActivity(intent);
6     }
7 });

运行程序,在MainActivity界面点击按钮进入到JumpActivity,然后在按JumpActivity中的返回按钮,又会进入到MainActivity,查看logcat中的打印信息:

其实从打印信息中就可以看出了,在JumpActivity中启动MainActivity时,会发现返回栈中已经存在了一个MainActivity实例,并且在JumpActivity的下面,于是JumpActivity会从返回栈中出栈,而MainActivity重新成为了栈顶活动,因此MainActivity中的onRestart()方法和JumpActivity的onDestroy()方法会执行。现在返回栈中只剩下一个MainActivity的实例了,按一下Back键就可以退出程序。

(4)singleInstance:指定为singleInstance模式的活动会启动一个新的返回栈来管理这个活动。
适用场景:共享活动实例的问题
代码测试:
修改AndroidManifest.xml中JumpActivity的启动模式:

1 <activity
2 android:name=".JumpActivity"
3 android:launchMode="singleInstance">
4 
5 </activity>

然后修改MainActivity中onCreate()方法的代码:

1 Log.d("MainActivity", "Task id is "+getTaskId());
2 btn_jump = findViewById(R.id.btn_jump);
3 btn_jump.setOnClickListener(new View.OnClickListener() {
4 @Override
5 public void onClick(View v) {
6     Intent intent = new Intent(MainActivity.this,JumpActivity.class);
7     startActivity(intent);
8     }
9 });

在JumpActivity的onCreate()方法中打印当前返回栈的ID:

1 Log.d("JumpActivity", "Task id is "+getTaskId());

并修改它的点击事件:

1 btn_jump_back.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4         Intent intent = new Intent(JumpActivity.this,ThirdActivity.class);
5         startActivity(intent);
6     }
7 });        

创建一个TiridActivity,同上修改onCreate()方法:

1 Log.d("ThirdActivity","Task id is "+getTaskId());

运行程序:在MainActivity界面点击按钮进入JumpActivity,然后再点击按钮进入TiridActivity。

查看logcat中的打印信息,如图所示:

可以看到,JumpActivity的Task id不同于MainActivity和TiridActivity,这说明JumpActivity确实存放在一个单独的返回栈中,而且这个栈中只有JumpActivity这一个活动。然后我们按下Back键进行返回,你会发现TiridActivity直接返回到了MainActivity,再按下Back键又会返回到JumpActivity,再按下Back键才会退出程序。原因:由于MainActivity和TiridActivity是存放在同一个栈里面的,当在TiridActivity界面按下Back键,TiridActivity会从返回栈中出栈,那么MainActivity就会成为栈顶活动显示在界面上,因此也就出现了从TiridActivity直接返回到了MainActivity的情况。然后在MainActivity界面再次按Back键,这时当前的返回栈已经空了,于是显示了另一个返回栈的栈顶活动,即JumpActivity。最后再按Back键,这时所有返回栈都已经空了,也就自然退出了程序。

原文地址:https://www.cnblogs.com/remote/p/10136955.html