活动的启动模式
在实际项目中我们应该根据特定的需求为每个活动指定恰当的启动模式,启动模式一共有四种:standard、singleTop、singleTask和singleInstance,可以在AndroidManifest.xml中通过给标签指定android:launchMode属性来选择启动模式。
standard
-
standard是活动默认的启动模式,在不进行显示指定的情况下,所有活动都会自动使用这种启动模式
-
在standard模式(即默认情况)下,每当启动一个新的活动,他就会返回栈中入栈,并处于栈顶的位置。对于使用standard模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例
-
实例
//在FristActivity活动上面启动FristActivity活动 public class FristActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前活动的实例 Log.d("FristActivity", this.toString()); setContentView(R.layout.frist_layout); //通过findViewById找到Button实例 Button button1 = (Button) findViewById(R.id.button_1); //setOnClickListener给按钮注册一个监听器,点击按钮时执行监听中的onClick时间,弹出Toast button1.setOnClickListener(new View.OnClickListener() { //在FristActivity活动上面启动FristActivity活动 @Override public void onClick(View v) { Intent intent = new Intent(FristActivity.this,FristActivity.class); startActivity(intent); } }); } }
-
standard模式示意图
singleTop
-
当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例
-
实例
//在AndroidManifest.xml中修改FristActivity的启动模式 <activity android:name=".FristActivity" android:launchMode="singleTop" android:label="This is FristActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> //在FristActivity活动上面启动FristActivity活动 public class FristActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前活动的实例 Log.d("FristActivity", this.toString()); setContentView(R.layout.frist_layout); //通过findViewById找到Button实例 Button button1 = (Button) findViewById(R.id.button_1); //setOnClickListener给按钮注册一个监听器,点击按钮时执行监听中的onClick时间,弹出Toast button1.setOnClickListener(new View.OnClickListener() { //在FristActivity活动上面启动FristActivity活动 @Override public void onClick(View v) { Intent intent = new Intent(FristActivity.this,FristActivity.class); startActivity(intent); } }); } } //重新运行后,从logcat会看到已经创建了一个FristActivity的实例,但是之后再点击多少次按钮都不会再有新的打印信息出现,因为目前FristActivity已经处于返回栈的栈顶,每次想要再启动一个FristActivity时会直接使用栈顶的活动,因此,FristActivity实例也只有一个,仅按一次Back键可以退出程序 //但是FristActivity并未处于顶端的时候,这时候在启动FristActivity,还是会创建新的实例 //在FristActivity活动上面启动SecondActivity活动 public class FristActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前活动的实例 Log.d("FristActivity", this.toString()); setContentView(R.layout.frist_layout); //通过findViewById找到Button实例 Button button1 = (Button) findViewById(R.id.button_1); //setOnClickListener给按钮注册一个监听器,点击按钮时执行监听中的onClick时间,弹出Toast button1.setOnClickListener(new View.OnClickListener() { //在FristActivity活动上面启动FristActivity活动 @Override public void onClick(View v) { Intent intent = new Intent(FristActivity.this,SecondActivity.class); startActivity(intent); } }); } } //在SecondActivity活动上面启动FristActivity活动 public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_layout); Button button2 = (Button) findViewById(R.id.button_2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this,FristActivity.class); startActivity(intent); } }); } } //通过打印结果可以看到,系统创建了两个不同的FristActivity实例,这是由于SecondActivity中再次启动FristActivity时,栈顶活动已经变成了SecondActivity,因此会再创建一个新的FristActivity实例,现在按下Back键会返回SecondActivity,再次按下Back键又会回到FristActivity,再按一次Back键才会退出程序
-
示意图
singleTask
-
当活动的启动模式指定为singleTask时,每次启动该活动时系统首先会在返回栈中检查时候存在该活动的实例,如果发现已经存在则直接使用该实例,并把这个活动之上的所有活动统统出栈,如果没有发现则会创建一个新的活动实例
-
实例
//在AndroidManifest.xml中修改FristActivity的启动模式 <activity android:name=".FristActivity" android:launchMode="singleTask" android:label="This is FristActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> //在FristActivity活动上面启动SecondActivity活动 public class FristActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前活动的实例 Log.d("FristActivity","onResrart")); setContentView(R.layout.frist_layout); //通过findViewById找到Button实例 Button button1 = (Button) findViewById(R.id.button_1); //setOnClickListener给按钮注册一个监听器,点击按钮时执行监听中的onClick时间,弹出Toast button1.setOnClickListener(new View.OnClickListener() { //在FristActivity活动上面启动FristActivity活动 @Override public void onClick(View v) { Intent intent = new Intent(FristActivity.this,SecondActivity.class); startActivity(intent); } }); } } //SecondActivity中添加onDestory()方法 public class SecondActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); Log.d("SecondActivity", "onDestroy"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("SecondActivity", this.toString()); setContentView(R.layout.second_layout); Button button2 = (Button) findViewById(R.id.button_2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this,FristActivity.class); startActivity(intent); } }); } } //重新运行程序,在FristActivity界面点击按钮进入SecondActivity,然后SecondActivity界面点击按钮,又会重新回到FristActivity //通过打印信息可得出在SecondActivity中启动FristActivity时,会发现返回栈中已经存在了一个FristActivity,并且是在SecondActivity的下面,于是SecondActivity会从返回栈中出栈,而FristActivity重新成为了栈顶活动,因此FristActivity的onResrart()和SecondActivity中的onDestroy()会被执行,现在栈中只剩FristActivity实例了,所以按一下Back就可以返回
-
示意图
singleInstance
-
不同于上述三种模式,指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动(其实如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)
-
**举例:假设程序中有一个活动是允许其他程序调用的,如果想实现其他程序和本程序可以共享这个活动的实例,使用前三种方式是做不到的,,因为每个程序都有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用singleInstance可以解决这个问题, ** 在singleInstance模式下会有一个单独的返回栈来管理这个活动,不管哪个应用程序来访问这个活动,都共用的同一个返回栈,这样也就解决了共享实例的问题
//配置AndroidManifest.xml 设置SecondActivity的启动模式为singleInstance <activity android:name=".SecondActivity" android:launchMode="singleInstance"> <intent-filter> <!-- 指定SecondActivity的name为com.example.activitytest.ACTION_START --> <action android:name="com.example.activitytest.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> <!-- 为了更精确的指定当前的活动,要在<intent-filter>标签中配置<data> --> <data android:host="www.baidu.com" android:scheme="http://" /> </intent-filter> </activity> //修改FristActicity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前返回栈的id Log.d("FristActivity","This id is" + getTaskId()); setContentView(R.layout.frist_layout); //通过findViewById找到Button实例 Button button1 = (Button) findViewById(R.id.button_1); //setOnClickListener给按钮注册一个监听器,点击按钮时执行监听中的onClick时间,弹出Toast button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(FristActivity.this,SecondActivity.class); startActivity(intent); } }); } //修改SecondActivity package com.example.activitytest; public class SecondActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); Log.d("SecondActivity", "onDestroy"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前返回栈的id Log.d("SecondActivity", "This id is" + getTaskId()); setContentView(R.layout.second_layout); Button button2 = (Button) findViewById(R.id.button_2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this,ThirdActivity.class); startActivity(intent); } }); } } //修改ThirdActivity public class ThirdActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //打印当前返回栈的id Log.d("ThirdActivity", "Task id is" + getTaskId()); setContentView(R.layout.third_layout); } } //结果:SecondActivity的Task id不同于FristActivity和ThirdActivity,说明SecondActivity是单独存在在一个返回栈的,而且这个栈中只有SecondActivity这一个活动 //然后按下Back,会从ThirdActivity返回FristActivity,再按Back会从FristActivity返回到SecondActivity //因为 ThirdActivity和FristActivity存放在同一个返回栈里,当在ThirdActivity按下Back键,ThirdActivity会从返回栈里出栈,那么FristActivity就成为了栈顶活动显示在界面上,因此也就出现了ThirdActivity直接返回到FristActivity的情况, //而再次按下Back键,当前返回栈已经空了,所以会返回另一个返回栈的活动,即SecondActivity,最后再按Back键,所有返回栈都空了,也就退出了程序
-
示意图