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:andro 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: 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中的打印信息,如图所示:
然后我们按下Back键进行返回,你会发现TiridActivity直接返回到了MainActivity,再按下Back键又会返回到JumpActivity,再按下Back键才会退出程序。原因:由于MainActivity和TiridActivity是存放在同一个栈里面的,当在TiridActivity界面按下Back键,TiridActivity会从返回栈中出栈,那么MainActivity就会成为栈顶活动显示在界面上,因此也就出现了从TiridActivity直接返回到了MainActivity的情况。然后在MainActivity界面再次按Back键,这时当前的返回栈已经空了,于是显示了另一个返回栈的栈顶活动,即JumpActivity。最后再按Back键,这时所有返回栈都已经空了,也就自然退出了程序。