关于Android中launchMode的文章介绍的真心不少,广为流传而且介绍的最详细的莫过于这篇文章http://blog.csdn.net/android_tutor/article/details/6310015。但是这篇文章中关于singletask和singleinstance在评论中还是有些不解和争论,在此根据实例重点说下这两种模式:
实例简介:有两个Activity,分别为AActivity和BActivity,界面相同。点击按钮A和B,分别启动AActivity和BActivity,观察效果:
上代码:
layout_task.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/buttonStartA" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="StartA" > </Button> <Button android:id="@+id/buttonStartB" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="StartB" > </Button> </LinearLayout>
AActivity.java
package com.example.activitytask; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class AActivity extends Activity{ private static final String TMG = "ActivityTask"; private static int mIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_task) ; mIndex++ ; Log.i(TMG,"AActivity Create"+mIndex+" TaskId="+getTaskId()) ; Button _buttonStartA = (Button)findViewById(R.id.buttonStartA) ; _buttonStartA.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent _intent = new Intent(AActivity.this,AActivity.class) ; startActivity(_intent) ; } }) ; Button _buttonStartB = (Button)findViewById(R.id.buttonStartB) ; _buttonStartB.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent _intent = new Intent(AActivity.this,BActivity.class) ; startActivity(_intent) ; } }) ; } @Override protected void onDestroy() { super.onDestroy(); Log.i(TMG,"AActivity Destory"+mIndex+" TaskId="+getTaskId()) ; mIndex--; } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.i(TMG,"AActivity onNewIntent"+mIndex+" TaskId="+getTaskId()) ; } }
BActivity.java
package com.example.activitytask; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class BActivity extends Activity{ private static final String TMG = "ActivityTask"; private static int mIndex = 0 ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_task) ; mIndex++ ; Log.i(TMG,"BActivity Create"+mIndex+" TaskId="+getTaskId()) ; Button _buttonStartA = (Button)findViewById(R.id.buttonStartA) ; _buttonStartA.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent _intent = new Intent(BActivity.this,AActivity.class) ; startActivity(_intent) ; } }) ; Button _buttonStartB = (Button)findViewById(R.id.buttonStartB) ; _buttonStartB.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent _intent = new Intent(BActivity.this,BActivity.class) ; startActivity(_intent) ; } }) ; } @Override protected void onDestroy() { super.onDestroy(); Log.i(TMG,"BActivity Destory"+mIndex+" TaskId="+getTaskId()) ; mIndex--; } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.i(TMG,"BActivity onNewIntent"+mIndex+" TaskId="+getTaskId()) ; } }
1.设置两个Activity的android:launchMode="singleTask"
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.activitytask" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme" > <activity android:name="com.example.activitytask.AActivity" android:label="AActivity" android:launchMode="singleTask" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.activitytask.BActivity" android:label="BActivity" android:launchMode="singleTask" /> </application> </manifest>
程序刚启动时的打印结果
点击startB按钮打印效果
进入BActivity界面后,这时再点击startA按钮打印结果(先清屏)
这时我们发现BActivity销毁,此时再点击startB,BActivity重新创建
总结:当一个Activity被设置为singletask时
(1)它并没有创建新的任务栈(根据上面打印效果展示,AActivity和BActivity的TaskId都等于76)
(2)如果它已经存在于栈中,再次请求触发此Activity时,会调用此类实例的onNewIntent方法,不会重新创建新的实例
(3)如果此类所在的任务栈上面有其它Activity,那么其它的Activity会被销毁
2.设置两个Activity的android:launchMode="singleInstance"
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.activitytask" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme" > <activity android:name="com.example.activitytask.AActivity" android:label="AActivity" android:launchMode="singleInstance" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.activitytask.BActivity" android:label="BActivity" android:launchMode="singleInstance" /> </application> </manifest>
程序刚启动时的打印结果
点击startB按钮打印效果
进入BActivity界面后,这时再点击startA按钮打印结果(先清屏)
再点击startB按钮打印结果(先清屏)
总结:当一个Activity被设置为singleinstance时
(1)如果此Activity没有实例,它会创建一个新的任务栈。(TaskId一个81,一个82)(2)如果任务栈中已经有此实例,会调用onNewIntent方法,不会创建新的任务栈和实例
(3)独立成Taskstack ,并且有且仅有你自己 ,孤家寡人 。而且始终保持一个实例离栈的时候 , 先退当前的task ,再退另外的task