活动的启动模式
活动的启动模式一共有四种,分别是standard、singleTop、singleTask和singleInstance,
可以在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。
standard模式
standard模式是活动默认的启动模式。对于使用standard模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,
每次启动都会创建该活动的一个新的实例。
在ActivityTest项目中,修改FirstActivity中onCreate()的方法,代码如下所示:
protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.d("FirstActivity", this.toString()); //隐藏标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); //在活动中加载布局,使用setContentView()方法 setContentView(R.layout.first_layout); Button button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(FirstActivity.this,FirstActivity.class); startActivity(intent); } }); }
上述的代码,在FirstActivity的基础上启动FirstActivity。运行程序,然后在FirstActivity界面连续点击两次按钮,可以看到LogCat打印的信息如下图所示:
从打印的信息中,可以看出每点击一次按钮就会创建一个新的FirstActivity实例。此时返回栈中存在三个FirstActivity的实例,需要连续按三次Back键才会退出程序。
singleTop模式
当活动的启动模式是singleTop模式时,在启动活动的时候如果发现返回栈的栈顶已经是该活动,
则可以直接使用它,不会在创建新的活动的实例。
修改AndroidManifest.xml中FirstActivity的启动模式,代码如下:
<activity android:name=".FirstActivity" android:label="this is Firstactivity" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
重新运行程序,查看LogCat的打印信息,如下图所示:
在打印出来的信息中,只有一个FirstActivity的实例,此时无论按几次按钮,都不会有新的打印信息出现。
因为当前FirstActivity已经处于返回栈的栈顶,每当在启动一个FirstActivity时都会直接使用栈顶的活动。
不过当FirstActivity并未处于栈顶位置时,这时再启动FirstActivity,还会创建新的实例。
singleTask模式
在singleTop模式中,如果FirstActivity不在栈顶时,这是如果要启动FirstActivity时还需要创建FirstActivity的实例。
如果只想活动在整个程序上下文中只存在一个实例时,就要使用singleTask模式来实现。
当活动的启动模式指定为singleTask时,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,
如果发现存在则直接使用,并把在这个活动之上的所有活动统统出栈;如果发现没有就会创建一个新的活动实例。
修改AndroidManifest.xml中FirstActivity的启动模式,代码如下:
<activity android:name=".FirstActivity" android:label="this is Firstactivity" android:launchMode="singleTask" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
重新运行程序,查看LogCat打印的日志信息,如下图所示:
从打印信息可以看出,在SecondActivity中启动FirstActivity时,会发现返回栈中已经存在一个FirstActivity的实例,
并且在SecondActivity的下面,于是SecondActivity会从返回栈中出栈,而FirstActivity重新成为了栈顶活动,
所以FirstActivity的onStart()方法和SecondActivity的onDestroy()方法会得到执行。
singleInstance模式
指定为singleInstance模式的活动会启动一个新的返回栈来管理这个活动。每个应用程序都会有自己的返回栈,
同一个活动在不同的返回栈中入栈时必然是创建了新的实例。
使用singleInstance模式可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,
不管哪个应用来访问这个活动,都共用同一个返回栈。
修改AndroidManifest.xml文件中SecondActivity的启动模式,代码如下:
<activity android:name=".SecondActivity" android:launchMode="singleInstance" > <intent-filter> <action android:name="com.example.activitytest.ACTION_START"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.example.activitytest.MY_CATEGORY" /> </intent-filter> </activity>
代码中将SecondActivity的启动模式设为singleInstance,然后修改FirstActivity中onCreate()方法的代码,代码如下:
protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.d("FirstActivity", "Task id is " + getTaskId()); //隐藏标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); //在活动中加载布局,使用setContentView()方法 setContentView(R.layout.first_layout); Button button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(FirstActivity.this,SecondActivity.class); startActivity(intent); } }); }
在onCreate()方法中打印当前返回栈的id,然后修改SecondActivity中onCreate()方法的代码,代码如下:
protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.d("SecondActivity", "Task id is " + getTaskId()); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.second_layout); Button button2 = (Button)findViewById(R.id.button_2); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this,ThirdActivity.class); startActivity(intent); } }); }
同样在onCreate()方法中打印当前返回栈的id,然后修改按钮点击事件的代码,用于启动ThirdActivity。
最后修改ThirdActivity中onCreate()方法的代码,代码如下:
protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.d("ThirdActivity", "Task id is " + getTaskId()); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.third_layout); }
在onCreate()方法中打印当前返回栈的id。重新运行程序,在FirstActivity界面上点击按钮进入SecondActivity,
然后在SecondActivity界面点击按钮进入ThirdActivity。查看LogCat的打印信息,得到下图所示:
从打印信息中可以看到,SecondActivity的Task id与FirstActivity和ThirdActivity的不相同,
这就说明SecondActivity是放在一个单独的返回栈中。在ThirdActivity界面,按下Back键会直接回到FirstActivity界面,
再按下Back键又会返回到SecondActivity,再按下Back键才会退出程序。
原因是ThirdActivity和FirstActivity在同一个返回栈中,当从ThirdActivity界面按下Back键,
ThirdActivity会从返回栈中出栈,那么FirstActivity就成了栈顶活动而显示在界面上。
然后在FirstActivity界面再次按下Back键,这时当前的返回栈已经空了,于是就显示了另一个返回栈的栈顶活动,即SecondActivity。