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>
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:id="@+id/activity_main" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical" 7 tools:context="com.example.lesson9_activitylaunchmode.MainActivity"> 8 9 <Button 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:onClick="toMainActivity" 13 android:text="这是MainActivity 启动MainActivity" 14 android:textAllCaps="false" /> 15 16 <Button 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:onClick="toFirstActivity" 20 android:text="这是MainActivity 启动FirstActivity" 21 android:textAllCaps="false" /> 22 23 24 25 </LinearLayout>
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical"> 5 6 <Button 7 android:id="@+id/backMain" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:textAllCaps="false" 11 android:text="这是FirstActivity 返回MainActivity"/> 12 13 <Button 14 android:id="@+id/toSecond" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:textAllCaps="false" 18 android:text="这是FirstActivity 启动SecondActivity"/> 19 20 </LinearLayout>
1 public class MainActivity extends AppCompatActivity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 //打印地址 8 Log.e("MainActivity",this.toString()); 9 Log.e("MainActivity", "Task id is " + getTaskId()); 10 Toast.makeText(this,this.toString(),Toast.LENGTH_SHORT).show(); 11 } 12 13 public void toMainActivity(View v){ 14 //显示Intent 15 Intent intent = new Intent(MainActivity.this,MainActivity.class); 16 startActivity(intent); 17 18 } 19 20 public void toFirstActivity(View v){ 21 Intent intent = new Intent(MainActivity.this,FirstActivity.class); 22 startActivity(intent); 23 } 24 25 @Override 26 protected void onRestart() { 27 super.onRestart(); 28 Log.e("TAG","MainActivity onRestart"); 29 } 30 31 @Override 32 protected void onDestroy() { 33 super.onDestroy(); 34 Log.e("TAG","MainActivity onDestroy"); 35 } 36 }
1 public class FirstActivity extends AppCompatActivity { 2 @Override 3 protected void onCreate(@Nullable Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 Log.e("FirstActivity",this.toString()); 6 Log.e("FirstActivity", "Task id is " + getTaskId()); 7 setContentView(R.layout.first_layout); 8 9 Button backMain = (Button) findViewById(R.id.backMain); 10 Button toSecond = (Button) findViewById(R.id.toSecond); 11 12 backMain.setOnClickListener(new View.OnClickListener() { 13 @Override 14 public void onClick(View v) { 15 Intent intent = new Intent(FirstActivity.this,MainActivity.class); 16 startActivity(intent); 17 } 18 }); 19 20 toSecond.setOnClickListener(new View.OnClickListener() { 21 @Override 22 public void onClick(View v) { 23 Intent intent = new Intent(FirstActivity.this,SecondActivity.class); 24 startActivity(intent); 25 } 26 }); 27 28 } 29 30 @Override 31 protected void onDestroy() { 32 super.onDestroy(); 33 Log.e("TAG","FirstActivity onDestroy"); 34 } 35 }
1 public class SecondActivity extends AppCompatActivity { 2 @Override 3 protected void onCreate(@Nullable Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 Log.e("SecondActivity",this.toString()); 6 Log.e("SecondActivity", "Task id is " + getTaskId()); 7 8 Button btn = new Button(this); 9 btn.setText("这是SecondActivity"); 10 btn.setAllCaps(false); 11 12 setContentView(btn); 13 } 14 15 @Override 16 protected void onDestroy() { 17 super.onDestroy(); 18 Log.e("TAG","SecondActivity onDestroy"); 19 } 20 }
1、standard
standard是活动默认的启动模式,在不进行显示指定的情况下,所有活动都会自动使用这种启动模式。
每当启动一个新的活动,它就会在返回栈入栈,并处于栈顶的位置。对于使用standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
MainActivity在不指定launchMode的情况下是默认的standard模式
从打印信息中我们就可以看出,每点击一次按钮就会创建出一个新的FirstActivity 实例。
此时返回栈中也会存在三个FirstActivity的实例,因此你需要连按三次Back键才能退出程序。
standard 模式的原理示意图
2、singleTop
当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例
我们将MainActivity的launchMode改为singleTop
连续点击启动自己
可以看到除了第一次启动的打印信息之外,不会再有新的打印信息了
因为目前FirstActivity已经处于返回栈的栈顶,每当想要再启动一个FirstActivity 时都会直接使用栈顶的活动,
因此FirstActivity 也只会有一个实例,仅按一次Back 键就可以退出程序。
当点击按钮去启动FirstActivity的时候,然后在FirstActivity中点击按钮返回MainActivity
可以看到系统创建了两个不同的MainActivity 实例,这是由于在FirstActivity 中再次启动MainActivity 时,栈顶活动已经变成了FirstActivity,
因此会创建一个新的MainActivity实例。现在按下Back 键会返回到FirstActivity,再次按下Back 键又会回到MainActivity,再按一次Back 键才会退出程序。
singleTop 模式的原理示意图
3、SingleTask
当活动的启动模式指定为singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,
如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
我们将MainActivity的launchMode改为singleTask
在FirstActivity 中启动MainActivity 时,会发现返回栈中已经存在一个MainActivity 的实例,并且是在FirstActivity 的下面,
于是会从返回栈中出栈,而MainActivity 重新成为了栈顶活动,因此MainActivity的onRestart()方法和FirstActivity 的onDestroy()方法会得到执行。
现在返回栈中应该只剩下一个MainActivity 的实例了,按一下Back 键就可以退出程序。
singleTask 模式的原理示意图:
4、SingleInstance
指定为singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果singleTask 模式指定了不同的taskAffinity,也会启动一个新的返回栈)。
那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,应该如何实现呢?
使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。
而使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。
1 <activity 2 android:name=".MainActivity"> 3 <intent-filter> 4 <action android:name="android.intent.action.MAIN" /> 5 6 <category android:name="android.intent.category.LAUNCHER" /> 7 </intent-filter> 8 </activity> 9 <activity 10 android:name=".FirstActivity" 11 android:launchMode="singleInstance" /> 12 <activity android:name=".SecondActivity" />
我们将FirstActivity的LaunchMode改为SingleInstance
可以看到, FirstActivity的Task id 不同于MainActivity 和SecondActivity , 这说明FirstActivity确实是存放在一个单独的返回栈里的,而且这个栈中只有FirstActivity这一个活动。
然后我们按下Back 键进行返回,你会发现SecondActivity 竟然直接返回到了MainActivity ,再按下Back 键又会返回到FirstActivity,再按下Back 键才会退出程序,这是为什么呢?
其实原理很简单,由于MainActivity 和SecondActivity 是存放在同一个返回栈里的,当在SecondActivity 的界面按下Back 键,SecondActivity 会从返回栈中出栈,
那么MainActivity 就成为了栈顶活动显示在界面上,因此也就出现了从SecondActivity 直接返回到MainActivity 的情况。
然后在MainActivity 界面再次按下Back 键,这时当前的返回栈已经空了,于是就显示了另一个返回栈的栈顶活动,即FirstActivity。
最后再次按下Back 键,这时所有返回栈都已经空了,也就自然退出了程序。
singleInstance 模式的原理示意图: